Micron Document
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| SparkN0de-git | SparkN0de |
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Commit 6ff7a652bedfdc81001c7862a4e9d0d8ab08cb57


Parents : c0312bf
Author : Ivan <ivan@quad4.io>
Signature : Signature validation error
Date : 2026-04-22T18:40:11-05:00

refactor(codebase): format

Changes

86 files changed, 1121 insertions(+), 396 deletions(-)

M cx_setup.py +3 -1

Diff

diff --git a/cx_setup.py b/cx_setup.py
index c502d9c4..694209f2 100644
--- a/cx_setup.py
+++ b/cx_setup.py
@@ -20,7 +20,9 @@ changelog_path = ROOT / "CHANGELOG.md"
if changelog_path.exists():
include_files.append((str(changelog_path), "CHANGELOG.md"))
-frontend_licenses_path = ROOT / "meshchatx" / "src" / "backend" / "data" / "licenses_frontend.json"
+frontend_licenses_path = (
+ ROOT / "meshchatx" / "src" / "backend" / "data" / "licenses_frontend.json"
+)
if frontend_licenses_path.exists():
include_files.append((str(frontend_licenses_path), "licenses_frontend.json"))

diff --git a/meshchatx/meshchat.py b/meshchatx/meshchat.py
index 2183bbec..111bcaed 100644
--- a/meshchatx/meshchat.py
+++ b/meshchatx/meshchat.py
@@ -426,7 +426,9 @@ class ReticulumMeshChat:
@property
def rnpath_trace_handler(self):
- return self.current_context.rnpath_trace_handler if self.current_context else None
+ return (
+ self.current_context.rnpath_trace_handler if self.current_context else None
+ )
@rnpath_trace_handler.setter
def rnpath_trace_handler(self, value):
@@ -471,7 +473,11 @@ class ReticulumMeshChat:
@property
def community_interfaces_manager(self):
- return self.current_context.community_interfaces_manager if self.current_context else None
+ return (
+ self.current_context.community_interfaces_manager
+ if self.current_context
+ else None
+ )
@community_interfaces_manager.setter
def community_interfaces_manager(self, value):
@@ -480,7 +486,11 @@ class ReticulumMeshChat:
@property
def local_lxmf_destination(self):
- return self.current_context.local_lxmf_destination if self.current_context else None
+ return (
+ self.current_context.local_lxmf_destination
+ if self.current_context
+ else None
+ )
@local_lxmf_destination.setter
def local_lxmf_destination(self, value):
@@ -495,7 +505,11 @@ class ReticulumMeshChat:
@property
def storage_path(self):
- return self.current_context.storage_path if self.current_context else self.storage_dir
+ return (
+ self.current_context.storage_path
+ if self.current_context
+ else self.storage_dir
+ )
@storage_path.setter
def storage_path(self, value):
@@ -814,7 +828,10 @@ class ReticulumMeshChat:
match = False
# check if local identity or destination matches
if hasattr(link, "destination") and link.destination:
- if hasattr(link.destination, "identity") and link.destination.identity:
+ if (
+ hasattr(link.destination, "identity")
+ and link.destination.identity
+ ):
if link.destination.identity.hash == identity_hash_bytes:
match = True
@@ -971,7 +988,11 @@ class ReticulumMeshChat:
else:
continue
- laddr_no_nul = laddr_bytes[1:] if laddr_bytes.startswith(b"\0") else laddr_bytes
+ laddr_no_nul = (
+ laddr_bytes[1:]
+ if laddr_bytes.startswith(b"\0")
+ else laddr_bytes
+ )
if (
laddr_bytes in (target_bytes, target_no_nul)
@@ -1239,9 +1260,13 @@ class ReticulumMeshChat:
)
# Only add if not already there
- if not any(addr == (rpc_bind, rpc_port) for addr, _ in rpc_addrs):
+ if not any(
+ addr == (rpc_bind, rpc_port) for addr, _ in rpc_addrs
+ ):
rpc_addrs.append(((rpc_bind, rpc_port), "AF_INET"))
- if not any(addr == (shared_bind, shared_port) for addr, _ in rpc_addrs):
+ if not any(
+ addr == (shared_bind, shared_port) for addr, _ in rpc_addrs
+ ):
rpc_addrs.append(((shared_bind, shared_port), "AF_INET"))
except Exception as e:
print(f"Warning reading Reticulum config for ports: {e}")
@@ -1256,7 +1281,11 @@ class ReticulumMeshChat:
all_free = True
for addr, family_str in rpc_addrs:
try:
- family = socket.AF_INET if family_str == "AF_INET" else socket.AF_UNIX
+ family = (
+ socket.AF_INET
+ if family_str == "AF_INET"
+ else socket.AF_UNIX
+ )
s = socket.socket(family, socket.SOCK_STREAM)
s.settimeout(0.5)
try:
@@ -1316,12 +1345,15 @@ class ReticulumMeshChat:
try:
current_process = psutil.Process()
# We use kind='all' to catch both TCP and UNIX sockets
- for conn in current_process.net_connections(kind="all"):
+ for conn in current_process.net_connections(
+ kind="all"
+ ):
try:
match = False
if conn.laddr:
- if family_str == "AF_INET" and isinstance(
- conn.laddr, tuple
+ if (
+ family_str == "AF_INET"
+ and isinstance(conn.laddr, tuple)
):
# Match IP and port for IPv4
if conn.laddr.port == addr[1] and (
@@ -1357,13 +1389,15 @@ class ReticulumMeshChat:
target_addr.startswith(
b"\0",
)
- and current_laddr == target_addr[1:]
+ and current_laddr
+ == target_addr[1:]
)
or (
current_laddr.startswith(
b"\0",
)
- and target_addr == current_laddr[1:]
+ and target_addr
+ == current_laddr[1:]
)
):
match = True
@@ -1391,7 +1425,10 @@ class ReticulumMeshChat:
)
try:
- if hasattr(conn, "fd") and conn.fd != -1:
+ if (
+ hasattr(conn, "fd")
+ and conn.fd != -1
+ ):
try:
os.close(conn.fd)
except Exception as fd_err:
@@ -1420,14 +1457,22 @@ class ReticulumMeshChat:
if not all_free:
await asyncio.sleep(2)
for addr, family_str in rpc_addrs:
- if family_str == "AF_UNIX" and isinstance(addr, str) and addr.startswith("\0"):
+ if (
+ family_str == "AF_UNIX"
+ and isinstance(addr, str)
+ and addr.startswith("\0")
+ ):
with contextlib.suppress(Exception):
self._force_close_abstract_unix_addr(addr)
last_check_all_free = True
for addr, family_str in rpc_addrs:
try:
- family = socket.AF_INET if family_str == "AF_INET" else socket.AF_UNIX
+ family = (
+ socket.AF_INET
+ if family_str == "AF_INET"
+ else socket.AF_UNIX
+ )
s = socket.socket(family, socket.SOCK_STREAM)
try:
s.bind(addr)
@@ -1465,7 +1510,9 @@ class ReticulumMeshChat:
if abstract_unix_addr_in_use_after_wait:
original_instance_name = self._read_reticulum_instance_name()
base_name = original_instance_name or "default"
- switched_instance_name = f"{base_name}-reload-{os.getpid()}-{int(time.time())}"
+ switched_instance_name = (
+ f"{base_name}-reload-{os.getpid()}-{int(time.time())}"
+ )
self._write_reticulum_instance_name(switched_instance_name)
print(
"Abstract UNIX RPC address remained busy. "
@@ -1560,7 +1607,9 @@ class ReticulumMeshChat:
"type": "identity_switched",
"identity_hash": identity_hash,
"display_name": (
- self.config.display_name.get() if hasattr(self, "config") else "Unknown"
+ self.config.display_name.get()
+ if hasattr(self, "config")
+ else "Unknown"
),
},
),
@@ -1635,7 +1684,9 @@ class ReticulumMeshChat:
def list_identities(self):
return self.identity_manager.list_identities(
- self.identity.hash.hex() if hasattr(self, "identity") and self.identity else None,
+ self.identity.hash.hex()
+ if hasattr(self, "identity") and self.identity
+ else None,
)
def create_identity(self, display_name=None):
@@ -1643,7 +1694,9 @@ class ReticulumMeshChat:
def delete_identity(self, identity_hash):
current_hash = (
- self.identity.hash.hex() if hasattr(self, "identity") and self.identity else None
+ self.identity.hash.hex()
+ if hasattr(self, "identity") and self.identity
+ else None
)
return self.identity_manager.delete_identity(identity_hash, current_hash)
@@ -1843,7 +1896,9 @@ class ReticulumMeshChat:
sanitized = []
seen = set()
for pattern in ReticulumMeshChat.parse_discovery_patterns(value):
- cleaned = pattern.replace("\r", "").replace("\n", "").replace(",", "").strip()
+ cleaned = (
+ pattern.replace("\r", "").replace("\n", "").replace(",", "").strip()
+ )
if not cleaned:
continue
cleaned = "".join(ch for ch in cleaned if ch.isprintable()).strip()
@@ -1891,7 +1946,11 @@ class ReticulumMeshChat:
or interface.get("remote")
or interface.get("listen_ip")
)
- port = interface.get("port") or interface.get("target_port") or interface.get("listen_port")
+ port = (
+ interface.get("port")
+ or interface.get("target_port")
+ or interface.get("listen_port")
+ )
if host and port:
candidates.append(f"{host}:{port}")
return candidates
@@ -1901,7 +1960,8 @@ class ReticulumMeshChat:
if not patterns:
return False
candidates = [
- value.lower() for value in ReticulumMeshChat.discovery_filter_candidates(interface)
+ value.lower()
+ for value in ReticulumMeshChat.discovery_filter_candidates(interface)
]
for pattern in patterns:
normalized_pattern = str(pattern).lower()
@@ -1979,7 +2039,10 @@ class ReticulumMeshChat:
interface
for interface in interfaces
if (
- (not whitelist or ReticulumMeshChat.matches_discovery_pattern(whitelist, interface))
+ (
+ not whitelist
+ or ReticulumMeshChat.matches_discovery_pattern(whitelist, interface)
+ )
and not ReticulumMeshChat.matches_discovery_pattern(
blacklist,
interface,
@@ -2047,12 +2110,13 @@ class ReticulumMeshChat:
return
while self.running and ctx.running and ctx.session_id == session_id:
- auto_sync_interval_seconds = (
- ctx.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get()
+ auto_sync_interval_seconds = ctx.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get()
+ last_synced_at = (
+ ctx.config.lxmf_preferred_propagation_node_last_synced_at.get()
)
- last_synced_at = ctx.config.lxmf_preferred_propagation_node_last_synced_at.get()
should_sync = interval_action_due(
- auto_sync_interval_seconds is not None and auto_sync_interval_seconds > 0,
+ auto_sync_interval_seconds is not None
+ and auto_sync_interval_seconds > 0,
last_synced_at,
auto_sync_interval_seconds,
time.time(),
@@ -2079,11 +2143,16 @@ class ReticulumMeshChat:
aspect="nomadnetwork.node",
)
for node in known_nodes:
- if not self.running or not ctx.running or ctx.session_id != session_id:
+ if (
+ not self.running
+ or not ctx.running
+ or ctx.session_id != session_id
+ ):
break
self.queue_crawler_task(
node["destination_hash"],
- ctx.config.nomad_default_page_path.get() or "/page/index.mu",
+ ctx.config.nomad_default_page_path.get()
+ or "/page/index.mu",
context=ctx,
)
@@ -2097,7 +2166,10 @@ class ReticulumMeshChat:
# process tasks concurrently up to the limit
if tasks and self.running and ctx.running:
await asyncio.gather(
- *[self.process_crawler_task(task, context=ctx) for task in tasks],
+ *[
+ self.process_crawler_task(task, context=ctx)
+ for task in tasks
+ ],
)
except Exception as e:
@@ -2270,8 +2342,8 @@ class ReticulumMeshChat:
metrics["started_at"] = datetime.now(UTC).isoformat()
metrics["baseline_total_messages"] = ctx.database.messages.count_lxmf_messages()
- metrics["baseline_delivered_messages"] = ctx.database.messages.count_lxmf_messages_by_state(
- "delivered"
+ metrics["baseline_delivered_messages"] = (
+ ctx.database.messages.count_lxmf_messages_by_state("delivered")
)
metrics["messages_stored"] = 0
metrics["delivery_confirmations"] = 0
@@ -2452,11 +2524,15 @@ class ReticulumMeshChat:
"rx_bytes": peer_rx_bytes + unpeered_rx_bytes,
"tx_bytes": peer_tx_bytes,
"unpeered_rx_bytes": unpeered_rx_bytes,
- "static_peers": stats.get("static_peers", 0) if isinstance(stats, dict) else 0,
+ "static_peers": stats.get("static_peers", 0)
+ if isinstance(stats, dict)
+ else 0,
"discovered_peers": (
stats.get("discovered_peers", 0) if isinstance(stats, dict) else 0
),
- "total_peers": stats.get("total_peers", 0) if isinstance(stats, dict) else 0,
+ "total_peers": stats.get("total_peers", 0)
+ if isinstance(stats, dict)
+ else 0,
"max_peers": stats.get("max_peers") if isinstance(stats, dict) else None,
"delivery_limit_bytes": int(delivery_limit * 1000),
"propagation_limit_bytes": int(propagation_limit * 1000),
@@ -2603,7 +2679,11 @@ class ReticulumMeshChat:
},
)
- if hasattr(self, "reticulum") and self.reticulum and not self.reticulum.transport_enabled():
+ if (
+ hasattr(self, "reticulum")
+ and self.reticulum
+ and not self.reticulum.transport_enabled()
+ ):
guidance.append(
{
"id": "transport_disabled",
@@ -2668,7 +2748,9 @@ class ReticulumMeshChat:
matches.add(message["source_hash"])
# also check custom display names
- custom_names = self.database.announces.get_announces() # Or more specific if needed
+ custom_names = (
+ self.database.announces.get_announces()
+ ) # Or more specific if needed
for announce in custom_names:
custom_name = self.database.announces.get_custom_display_name(
announce["destination_hash"],
@@ -2993,7 +3075,17 @@ class ReticulumMeshChat:
or path.startswith(("/assets/", "/favicons/"))
or path in ("/manifest.json", "/service-worker.js")
or path.endswith(
- (".js", ".css", ".json", ".wasm", ".png", ".jpg", ".jpeg", ".ico", ".svg")
+ (
+ ".js",
+ ".css",
+ ".json",
+ ".wasm",
+ ".png",
+ ".jpg",
+ ".jpeg",
+ ".ico",
+ ".svg",
+ )
)
):
return await handler(request)
@@ -3026,7 +3118,17 @@ class ReticulumMeshChat:
path == "/"
or path.startswith(("/assets/", "/favicons/"))
or path.endswith(
- (".js", ".css", ".json", ".wasm", ".png", ".jpg", ".jpeg", ".ico", ".svg")
+ (
+ ".js",
+ ".css",
+ ".json",
+ ".wasm",
+ ".png",
+ ".jpg",
+ ".jpeg",
+ ".ico",
+ ".svg",
+ )
)
):
is_public = True
@@ -3408,7 +3510,8 @@ class ReticulumMeshChat:
return web.json_response(
{
"auth_enabled": self.auth_enabled,
- "password_set": self.config.auth_password_hash.get() is not None,
+ "password_set": self.config.auth_password_hash.get()
+ is not None,
"authenticated": actually_authenticated,
},
)
@@ -3417,7 +3520,8 @@ class ReticulumMeshChat:
return web.json_response(
{
"auth_enabled": self.auth_enabled,
- "password_set": self.config.auth_password_hash.get() is not None,
+ "password_set": self.config.auth_password_hash.get()
+ is not None,
"authenticated": False,
"error": str(e),
},
@@ -3672,7 +3776,9 @@ class ReticulumMeshChat:
async with session.get(url, allow_redirects=True) as response:
if response.status != 200:
return web.json_response(
- {"error": f"Failed to fetch release: {response.status}"},
+ {
+ "error": f"Failed to fetch release: {response.status}"
+ },
status=response.status,
)
data = await response.json(content_type=None)
@@ -3959,7 +4065,10 @@ class ReticulumMeshChat:
interface_details["type"] = interface_type
# if interface doesn't have enabled or interface_enabled setting already, enable it by default
- if "enabled" not in interface_details and "interface_enabled" not in interface_details:
+ if (
+ "enabled" not in interface_details
+ and "interface_enabled" not in interface_details
+ ):
interface_details["interface_enabled"] = "true"
# handle AutoInterface
@@ -4100,7 +4209,8 @@ class ReticulumMeshChat:
listen_ip_value = data.get("listen_ip")
listen_device_value = data.get("device")
if (listen_port_value not in (None, "")) and (
- listen_ip_value not in (None, "") or listen_device_value not in (None, "")
+ listen_ip_value not in (None, "")
+ or listen_device_value not in (None, "")
):
if is_port_in_use(
listen_ip_value,
@@ -4145,7 +4255,10 @@ class ReticulumMeshChat:
status=422,
)
transport_identity = data.get("transport_identity")
- if transport_identity is None or str(transport_identity).strip() == "":
+ if (
+ transport_identity is None
+ or str(transport_identity).strip() == ""
+ ):
return web.json_response(
{
"message": "Transport identity is required",
@@ -4166,7 +4279,8 @@ class ReticulumMeshChat:
else:
interface_details["connectable"] = (
"True"
- if str(connectable_value).lower() in {"true", "yes", "1", "on", "y"}
+ if str(connectable_value).lower()
+ in {"true", "yes", "1", "on", "y"}
else "False"
)
peers = data.get("peers")
@@ -4175,7 +4289,9 @@ class ReticulumMeshChat:
cleaned_peers = [str(p).strip() for p in peers if str(p).strip()]
elif peers is not None and str(peers).strip() != "":
cleaned_peers = [
- s.strip() for s in str(peers).replace(",", " ").split() if s.strip()
+ s.strip()
+ for s in str(peers).replace(",", " ").split()
+ if s.strip()
]
if not cleaned_peers:
return web.json_response(
@@ -4614,7 +4730,10 @@ class ReticulumMeshChat:
interfaces = self._get_interfaces_snapshot()
for interface_name, interface in interfaces.items():
# skip interface if not selected
- if selected_interface_names is not None and selected_interface_names != "":
+ if (
+ selected_interface_names is not None
+ and selected_interface_names != ""
+ ):
if interface_name not in selected_interface_names:
continue
@@ -4914,12 +5033,19 @@ class ReticulumMeshChat:
for conn in process.net_connections(kind="all"):
if conn.status == psutil.CONN_ESTABLISHED and conn.raddr:
# Check for common Reticulum shared instance ports or UNIX sockets
- if isinstance(conn.raddr, tuple) and conn.raddr[1] == 37428:
- shared_instance_address = f"{conn.raddr[0]}:{conn.raddr[1]}"
+ if (
+ isinstance(conn.raddr, tuple)
+ and conn.raddr[1] == 37428
+ ):
+ shared_instance_address = (
+ f"{conn.raddr[0]}:{conn.raddr[1]}"
+ )
break
if (
isinstance(conn.raddr, str)
- and ("rns" in conn.raddr or "reticulum" in conn.raddr)
+ and (
+ "rns" in conn.raddr or "reticulum" in conn.raddr
+ )
and ".sock" in conn.raddr
):
shared_instance_address = conn.raddr
@@ -4949,7 +5075,9 @@ class ReticulumMeshChat:
"shared_instance_bind",
fallback="127.0.0.1",
)
- shared_instance_address = f"{shared_bind}:{shared_port}"
+ shared_instance_address = (
+ f"{shared_bind}:{shared_port}"
+ )
except Exception:
pass
@@ -5027,7 +5155,9 @@ class ReticulumMeshChat:
"database_file_size": db_files["main_bytes"],
"database_files": db_files,
"sqlite": {
- "journal_mode": _safe_sqlite_pragma("journal_mode", "unknown"),
+ "journal_mode": _safe_sqlite_pragma(
+ "journal_mode", "unknown"
+ ),
"synchronous": _safe_sqlite_pragma("synchronous", None),
"wal_autocheckpoint": _safe_sqlite_pragma(
"wal_autocheckpoint",
@@ -5073,7 +5203,8 @@ class ReticulumMeshChat:
[],
),
"user_guidance": _safe_user_guidance(),
- "tutorial_seen": _safe_config_get("tutorial_seen", "false") == "true",
+ "tutorial_seen": _safe_config_get("tutorial_seen", "false")
+ == "true",
"changelog_seen_version": _safe_config_get(
"changelog_seen_version",
"0.0.0",
@@ -5282,7 +5413,9 @@ class ReticulumMeshChat:
async def docs_export(request):
try:
zip_data = self.docs_manager.export_docs()
- filename = f"meshchatx_docs_{datetime.now(UTC).strftime('%Y%m%d_%H%M%S')}.zip"
+ filename = (
+ f"meshchatx_docs_{datetime.now(UTC).strftime('%Y%m%d_%H%M%S')}.zip"
+ )
return web.Response(
body=zip_data,
content_type="application/zip",
@@ -5543,7 +5676,9 @@ class ReticulumMeshChat:
if self.database:
for item in identities:
if item.get("is_current"):
- item["message_count"] = self.database.messages.count_lxmf_messages()
+ item["message_count"] = (
+ self.database.messages.count_lxmf_messages()
+ )
break
return web.json_response(
{
@@ -5956,8 +6091,14 @@ class ReticulumMeshChat:
parsed_host = None
parsed_port = None
- host = s.get("target_host") or s.get("remote") or parsed_host
- port = s.get("target_port") or s.get("listen_port") or parsed_port
+ host = (
+ s.get("target_host") or s.get("remote") or parsed_host
+ )
+ port = (
+ s.get("target_port")
+ or s.get("listen_port")
+ or parsed_port
+ )
transport_id = s.get("transport_id")
if isinstance(transport_id, (bytes, bytearray)):
transport_id = transport_id.hex()
@@ -5992,8 +6133,10 @@ class ReticulumMeshChat:
return [to_jsonable(v) for v in obj]
return obj
- normalized_interfaces = ReticulumMeshChat.normalize_discovered_ifac_fields(
- to_jsonable(interfaces),
+ normalized_interfaces = (
+ ReticulumMeshChat.normalize_discovered_ifac_fields(
+ to_jsonable(interfaces),
+ )
)
return web.json_response(
@@ -6200,8 +6343,10 @@ class ReticulumMeshChat:
remote_identity = telephone_active_call.get_remote_identity()
if remote_identity:
caller_hash = remote_identity.hash.hex()
- contact = self.database.contacts.get_contact_by_identity_hash(
- caller_hash,
+ contact = (
+ self.database.contacts.get_contact_by_identity_hash(
+ caller_hash,
+ )
)
if not contact:
# Don't report active call if contacts-only is on and caller is not a contact
@@ -6928,7 +7073,11 @@ class ReticulumMeshChat:
ringtone_id = None
has_custom = ringtone_id is not None
- ringtone = self.database.ringtones.get_by_id(ringtone_id) if has_custom else None
+ ringtone = (
+ self.database.ringtones.get_by_id(ringtone_id)
+ if has_custom
+ else None
+ )
return web.json_response(
{
@@ -7287,7 +7436,9 @@ class ReticulumMeshChat:
if sm is not None and sm > 0:
search_max = min(int(sm), 10_000)
- include_blocked = request.query.get("include_blocked", "false").lower() == "true"
+ include_blocked = (
+ request.query.get("include_blocked", "false").lower() == "true"
+ )
blocked_identity_hashes = None
if not include_blocked:
@@ -7485,7 +7636,9 @@ class ReticulumMeshChat:
results = self.database.announces.get_favourites(aspect=aspect)
# process favourites
- favourites = [convert_db_favourite_to_dict(favourite) for favourite in results]
+ favourites = [
+ convert_db_favourite_to_dict(favourite) for favourite in results
+ ]
return web.json_response(
{
@@ -7680,7 +7833,9 @@ class ReticulumMeshChat:
* 100, # convert to percentage
"messages_received": self.message_router.propagation_transfer_last_result,
"messages_stored": sync_metrics["messages_stored"],
- "delivery_confirmations": sync_metrics["delivery_confirmations"],
+ "delivery_confirmations": sync_metrics[
+ "delivery_confirmations"
+ ],
"messages_hidden": sync_metrics["messages_hidden"],
},
"local_propagation_node": self.get_local_propagation_node_stats(),
@@ -7787,19 +7942,25 @@ class ReticulumMeshChat:
local_destination_hash = local_destination_hash_raw
else:
local_destination_hash = None
- local_stats = self.get_local_propagation_node_stats(context=ctx) if ctx else None
+ local_stats = (
+ self.get_local_propagation_node_stats(context=ctx) if ctx else None
+ )
for announce in results:
# find an lxmf.delivery announce for the same identity hash, so we can use that as an "operater by" name
lxmf_delivery_results = self.database.announces.get_filtered_announces(
aspect="lxmf.delivery",
identity_hash=announce["identity_hash"],
)
- lxmf_delivery_announce = lxmf_delivery_results[0] if lxmf_delivery_results else None
+ lxmf_delivery_announce = (
+ lxmf_delivery_results[0] if lxmf_delivery_results else None
+ )
# find a nomadnetwork.node announce for the same identity hash, so we can use that as an "operated by" name
- nomadnetwork_node_results = self.database.announces.get_filtered_announces(
- aspect="nomadnetwork.node",
- identity_hash=announce["identity_hash"],
+ nomadnetwork_node_results = (
+ self.database.announces.get_filtered_announces(
+ aspect="nomadnetwork.node",
+ identity_hash=announce["identity_hash"],
+ )
)
nomadnetwork_node_announce = (
nomadnetwork_node_results[0] if nomadnetwork_node_results else None
@@ -7888,7 +8049,9 @@ class ReticulumMeshChat:
else ctx.config.lxmf_local_propagation_node_enabled.get()
),
"per_transfer_limit": int(
- getattr(ctx.message_router, "propagation_per_transfer_limit", 0),
+ getattr(
+ ctx.message_router, "propagation_per_transfer_limit", 0
+ ),
),
"is_local_node": True,
"local_node_stats": local_stats,
@@ -8095,7 +8258,8 @@ class ReticulumMeshChat:
# get signal metrics from latest lxmf message if it's more recent than the announce
if latest_lxmf_message is not None and (
- latest_announce_at is None or latest_lxmf_message_at > latest_announce_at
+ latest_announce_at is None
+ or latest_lxmf_message_at > latest_announce_at
):
snr = latest_lxmf_message["snr"]
rssi = latest_lxmf_message["rssi"]
@@ -8137,7 +8301,8 @@ class ReticulumMeshChat:
# wait until we have a path, or give up after the configured timeout
while (
- not RNS.Transport.has_path(destination_hash) and time.time() < timeout_after_seconds
+ not RNS.Transport.has_path(destination_hash)
+ and time.time() < timeout_after_seconds
):
await asyncio.sleep(0.1)
@@ -8827,7 +8992,9 @@ class ReticulumMeshChat:
if ts is not None and hasattr(ts, "isoformat"):
bot["last_announce_at"] = ts.isoformat()
else:
- bot["last_announce_at"] = str(ts) if ts is not None else None
+ bot["last_announce_at"] = (
+ str(ts) if ts is not None else None
+ )
return web.json_response(
{
"status": status,
@@ -9077,8 +9244,8 @@ class ReticulumMeshChat:
)
# get outbound ticket expiry for this lxmf destination
- lxmf_outbound_ticket_expiry = self.message_router.get_outbound_ticket_expiry(
- destination_hash_bytes
+ lxmf_outbound_ticket_expiry = (
+ self.message_router.get_outbound_ticket_expiry(destination_hash_bytes)
)
return web.json_response(
@@ -9101,7 +9268,9 @@ class ReticulumMeshChat:
# ensure transport_id is hex as json_response can't serialize bytes
if "transport_id" in interface_stats:
- interface_stats["transport_id"] = interface_stats["transport_id"].hex()
+ interface_stats["transport_id"] = interface_stats[
+ "transport_id"
+ ].hex()
# ensure probe_responder is hex as json_response can't serialize bytes
if (
@@ -9126,7 +9295,9 @@ class ReticulumMeshChat:
].hex()
if interface.get("ifac_signature"):
- interface["ifac_signature"] = interface["ifac_signature"].hex()
+ interface["ifac_signature"] = interface[
+ "ifac_signature"
+ ].hex()
try:
if interface.get("hash"):
@@ -9167,7 +9338,9 @@ class ReticulumMeshChat:
if destination_hashes:
hash_set = {h.lower() for h in destination_hashes if isinstance(h, str)}
- all_paths = [p for p in all_paths if p["hash"].hex().lower() in hash_set]
+ all_paths = [
+ p for p in all_paths if p["hash"].hex().lower() in hash_set
+ ]
total_count = len(all_paths)
@@ -9235,7 +9408,9 @@ class ReticulumMeshChat:
file_attachments_field = None
if "file_attachments" in fields:
file_attachments = []
- for file_attachment in data["lxmf_message"]["fields"]["file_attachments"]:
+ for file_attachment in data["lxmf_message"]["fields"][
+ "file_attachments"
+ ]:
file_name = file_attachment["file_name"]
file_bytes = base64.b64decode(file_attachment["file_bytes"])
file_attachments.append(LxmfFileAttachment(file_name, file_bytes))
@@ -9274,7 +9449,9 @@ class ReticulumMeshChat:
reply_to_hash = None
if "reply_to_hash" in data["lxmf_message"]:
reply_to_hash = data["lxmf_message"]["reply_to_hash"]
- reply_quoted_content = data["lxmf_message"].get("reply_quoted_content") or None
+ reply_quoted_content = (
+ data["lxmf_message"].get("reply_quoted_content") or None
+ )
try:
# send lxmf message to destination
@@ -9445,7 +9622,8 @@ class ReticulumMeshChat:
# convert to response json
lxmf_messages = [
- convert_db_lxmf_message_to_dict(db_lxmf_message) for db_lxmf_message in results
+ convert_db_lxmf_message_to_dict(db_lxmf_message)
+ for db_lxmf_message in results
]
return web.json_response(
@@ -9582,7 +9760,9 @@ class ReticulumMeshChat:
data = await request.json()
except Exception:
return web.json_response({"message": "invalid json"}, status=400)
- destination_hash = data.get("destination_hash") if isinstance(data, dict) else None
+ destination_hash = (
+ data.get("destination_hash") if isinstance(data, dict) else None
+ )
if not destination_hash:
return web.json_response(
{"message": "missing destination_hash"},
@@ -9807,7 +9987,9 @@ class ReticulumMeshChat:
@routes.get("/api/v1/lxmf/folders/export")
async def lxmf_folders_export(request):
folders = [dict(f) for f in self.database.messages.get_all_folders()]
- mappings = [dict(m) for m in self.database.messages.get_all_conversation_folders()]
+ mappings = [
+ dict(m) for m in self.database.messages.get_all_conversation_folders()
+ ]
return web.json_response({"folders": folders, "mappings": mappings})
@routes.post("/api/v1/lxmf/folders/import")
@@ -9936,10 +10118,8 @@ class ReticulumMeshChat:
db_message.get("content"),
db_message.get("title"),
):
- latest_user_facing = (
- self.database.messages.get_latest_user_facing_incoming_message(
- other_user_hash,
- )
+ latest_user_facing = self.database.messages.get_latest_user_facing_incoming_message(
+ other_user_hash,
)
if latest_user_facing is None:
continue
@@ -9954,7 +10134,10 @@ class ReticulumMeshChat:
last_read_dt = last_read_dt.replace(
tzinfo=UTC,
)
- if latest_user_facing["timestamp"] <= last_read_dt.timestamp():
+ if (
+ latest_user_facing["timestamp"]
+ <= last_read_dt.timestamp()
+ ):
continue
except (ValueError, TypeError):
pass
@@ -9973,8 +10156,10 @@ class ReticulumMeshChat:
display_name = self.get_lxmf_conversation_name(
other_user_hash,
)
- custom_display_name = self.database.announces.get_custom_display_name(
- other_user_hash,
+ custom_display_name = (
+ self.database.announces.get_custom_display_name(
+ other_user_hash,
+ )
)
# Determine latest message data
@@ -9993,9 +10178,9 @@ class ReticulumMeshChat:
"display_name": display_name,
"custom_display_name": custom_display_name,
"lxmf_user_icon": dict(icon) if icon else None,
- "latest_message_preview": (latest_message_data["content"] or "")[
- :100
- ],
+ "latest_message_preview": (
+ latest_message_data["content"] or ""
+ )[:100],
"updated_at": datetime.fromtimestamp(
latest_message_data["timestamp"] or 0,
UTC,
@@ -10085,10 +10270,8 @@ class ReticulumMeshChat:
conv.get("content"),
conv.get("title"),
):
- latest_user_facing = (
- self.database.messages.get_latest_user_facing_incoming_message(
- other_user_hash,
- )
+ latest_user_facing = self.database.messages.get_latest_user_facing_incoming_message(
+ other_user_hash,
)
if latest_user_facing is None:
continue
@@ -10102,7 +10285,10 @@ class ReticulumMeshChat:
last_read_dt = last_read_dt.replace(
tzinfo=UTC,
)
- if latest_user_facing["timestamp"] <= last_read_dt.timestamp():
+ if (
+ latest_user_facing["timestamp"]
+ <= last_read_dt.timestamp()
+ ):
continue
except (ValueError, TypeError):
pass
@@ -10260,7 +10446,9 @@ class ReticulumMeshChat:
formatted = {}
for h, info in identities.items():
formatted[h.hex()] = {
- "source": info.get("source", b"").hex() if info.get("source") else None,
+ "source": info.get("source", b"").hex()
+ if info.get("source")
+ else None,
"until": info.get("until"),
"reason": info.get("reason"),
}
@@ -10710,7 +10898,9 @@ class ReticulumMeshChat:
pack_id = int(request.match_info.get("pack_id", "0"))
except ValueError:
return web.json_response({"error": "invalid_pack_id"}, status=400)
- with_stickers = request.query.get("with_stickers", "false").lower() == "true"
+ with_stickers = (
+ request.query.get("with_stickers", "false").lower() == "true"
+ )
if with_stickers:
ok = self.database.sticker_packs.delete_with_stickers(
pack_id,
@@ -10979,7 +11169,9 @@ class ReticulumMeshChat:
"destination_hash": r["destination_hash"],
"timestamp": r["timestamp"],
"telemetry": unpacked,
- "physical_link": json.loads(r["physical_link"]) if r["physical_link"] else None,
+ "physical_link": json.loads(r["physical_link"])
+ if r["physical_link"]
+ else None,
"updated_at": r["updated_at"],
},
)
@@ -11120,7 +11312,9 @@ class ReticulumMeshChat:
if path.startswith("/api/"):
return response
if path.endswith((".js", ".mjs")):
- response.headers["Content-Type"] = "application/javascript; charset=utf-8"
+ response.headers["Content-Type"] = (
+ "application/javascript; charset=utf-8"
+ )
elif path.endswith(".css"):
response.headers["Content-Type"] = "text/css; charset=utf-8"
elif path.endswith(".json"):
@@ -11228,7 +11422,9 @@ class ReticulumMeshChat:
return
sources = [
s.strip()
- for s in extra_str.replace("\n", ",").replace(";", ",").split(",")
+ for s in extra_str.replace("\n", ",")
+ .replace(";", ",")
+ .split(",")
if s.strip()
]
for s in sources:
@@ -11367,7 +11563,9 @@ class ReticulumMeshChat:
def run(self, host, port, launch_browser: bool, enable_https: bool = True):
# create route table
routes = web.RouteTableDef()
- auth_middleware, mime_type_middleware, security_middleware = self._define_routes(routes)
+ auth_middleware, mime_type_middleware, security_middleware = (
+ self._define_routes(routes)
+ )
ssl_context = None
use_https = enable_https
@@ -11638,7 +11836,9 @@ class ReticulumMeshChat:
# Local node selected as preferred: no transport path lookup is needed.
# Mark sync as complete immediately to avoid getting stuck in PR_PATH_REQUESTED.
with contextlib.suppress(Exception):
- ctx.message_router.propagation_transfer_state = ctx.message_router.PR_COMPLETE
+ ctx.message_router.propagation_transfer_state = (
+ ctx.message_router.PR_COMPLETE
+ )
ctx.message_router.propagation_transfer_progress = 1.0
ctx.message_router.propagation_transfer_last_result = 0
await self.send_config_to_websocket_clients(context=ctx)
@@ -12876,7 +13076,9 @@ class ReticulumMeshChat:
bytes.fromhex(destination_hash_hex)
raw_bytes = bytes.fromhex(public_key_hex)
- public_key_bytes = raw_bytes[:32] if len(raw_bytes) >= 32 else raw_bytes
+ public_key_bytes = (
+ raw_bytes[:32] if len(raw_bytes) >= 32 else raw_bytes
+ )
identity = RNS.Identity(create_keys=False)
if not identity.load_public_key(public_key_bytes):
@@ -12887,8 +13089,10 @@ class ReticulumMeshChat:
raise ValueError("Invalid LXMA public key")
remote_identity_hash = identity.hash.hex()
- existing_contact = self.database.contacts.get_contact_by_identity_hash(
- remote_identity_hash,
+ existing_contact = (
+ self.database.contacts.get_contact_by_identity_hash(
+ remote_identity_hash,
+ )
)
contact_name = (
existing_contact["name"]
@@ -13560,7 +13764,10 @@ class ReticulumMeshChat:
# ensure we're not storing the user's own icon with a peer's hash
# only store icons for remote peers, not for the local user
- if ctx.local_lxmf_destination and destination_hash == ctx.local_lxmf_destination.hexhash:
+ if (
+ ctx.local_lxmf_destination
+ and destination_hash == ctx.local_lxmf_destination.hexhash
+ ):
print(f"skipping icon update for local user's own hash: {destination_hash}")
return
@@ -13684,7 +13891,8 @@ class ReticulumMeshChat:
and (
SidebandCommands.TELEMETRY_REQUEST in command
or str(SidebandCommands.TELEMETRY_REQUEST) in command
- or f"0x{SidebandCommands.TELEMETRY_REQUEST:02x}" in command
+ or f"0x{SidebandCommands.TELEMETRY_REQUEST:02x}"
+ in command
)
)
or (
@@ -13760,7 +13968,9 @@ class ReticulumMeshChat:
# check for spam keywords
is_spam = False
message_title = lxmf_message.title if hasattr(lxmf_message, "title") else ""
- message_content = lxmf_message.content if hasattr(lxmf_message, "content") else ""
+ message_content = (
+ lxmf_message.content if hasattr(lxmf_message, "content") else ""
+ )
if isinstance(message_content, bytes):
message_content = message_content.decode("utf-8", errors="replace")
elif message_content is None:
@@ -13797,8 +14007,9 @@ class ReticulumMeshChat:
)
return
# strip attachments from strangers (non-contacts) if setting is enabled
- if ctx.config.block_attachments_from_strangers.get() and not self._is_contact(
- source_hash, context=ctx
+ if (
+ ctx.config.block_attachments_from_strangers.get()
+ and not self._is_contact(source_hash, context=ctx)
):
for key in (
LXMF.FIELD_FILE_ATTACHMENTS,
@@ -13847,7 +14058,9 @@ class ReticulumMeshChat:
for entry in stream:
if isinstance(entry, (list, tuple)) and len(entry) >= 3:
entry_source = (
- entry[0].hex() if isinstance(entry[0], bytes) else entry[0]
+ entry[0].hex()
+ if isinstance(entry[0], bytes)
+ else entry[0]
)
entry_timestamp = entry[1]
entry_data = entry[2]
@@ -13871,7 +14084,9 @@ class ReticulumMeshChat:
background_colour = "#" + icon_appearance[2].hex()
local_hash = (
- ctx.local_lxmf_destination.hexhash if ctx.local_lxmf_destination else None
+ ctx.local_lxmf_destination.hexhash
+ if ctx.local_lxmf_destination
+ else None
)
source_hash = lxmf_message.source_hash.hex()
@@ -13882,8 +14097,12 @@ class ReticulumMeshChat:
pass
else:
local_icon_name = ctx.config.lxmf_user_icon_name.get()
- local_icon_fg = ctx.config.lxmf_user_icon_foreground_colour.get()
- local_icon_bg = ctx.config.lxmf_user_icon_background_colour.get()
+ local_icon_fg = (
+ ctx.config.lxmf_user_icon_foreground_colour.get()
+ )
+ local_icon_bg = (
+ ctx.config.lxmf_user_icon_background_colour.get()
+ )
# if incoming icon matches our own, skip storing and clear any mistaken stored copy
# for now, but this will need to be updated later if two users do have the same icon
@@ -13994,7 +14213,9 @@ class ReticulumMeshChat:
self.send_message(
destination_hash=mapping["original_sender_hash"],
content=lxmf_message.content,
- title=lxmf_message.title if hasattr(lxmf_message, "title") else "",
+ title=lxmf_message.title
+ if hasattr(lxmf_message, "title")
+ else "",
image_field=image_field,
audio_field=audio_field,
file_attachments_field=file_attachments_field,
@@ -14013,7 +14234,10 @@ class ReticulumMeshChat:
for rule in rules:
# check source filter if set
- if rule["source_filter_hash"] and rule["source_filter_hash"] != source_hash:
+ if (
+ rule["source_filter_hash"]
+ and rule["source_filter_hash"] != source_hash
+ ):
continue
# find or create mapping for this (Source, Final Recipient) pair
@@ -14031,7 +14255,9 @@ class ReticulumMeshChat:
self.send_message(
destination_hash=rule["forward_to_hash"],
content=lxmf_message.content,
- title=lxmf_message.title if hasattr(lxmf_message, "title") else "",
+ title=lxmf_message.title
+ if hasattr(lxmf_message, "title")
+ else "",
sender_identity_hash=mapping["alias_hash"],
image_field=image_field,
audio_field=audio_field,
@@ -14130,7 +14356,10 @@ class ReticulumMeshChat:
# resend message
source_hash = lxmf_message.source_hash.hex()
router = ctx.message_router
- if ctx.forwarding_manager and source_hash in ctx.forwarding_manager.forwarding_routers:
+ if (
+ ctx.forwarding_manager
+ and source_hash in ctx.forwarding_manager.forwarding_routers
+ ):
router = ctx.forwarding_manager.forwarding_routers[source_hash]
router.handle_outbound(lxmf_message)
@@ -14174,13 +14403,19 @@ class ReticulumMeshChat:
deadline = time.time() + self._lxmf_path_wait_seconds()
if not RNS.Transport.has_path(destination_hash_bytes):
RNS.Transport.request_path(destination_hash_bytes)
- while not RNS.Transport.has_path(destination_hash_bytes) and time.time() < deadline:
+ while (
+ not RNS.Transport.has_path(destination_hash_bytes)
+ and time.time() < deadline
+ ):
await asyncio.sleep(0.1)
if RNS.Transport.has_path(destination_hash_bytes):
return True
RNS.Transport.request_path(destination_hash_bytes)
deadline = time.time() + max(15.0, self._lxmf_path_wait_seconds() * 0.5)
- while not RNS.Transport.has_path(destination_hash_bytes) and time.time() < deadline:
+ while (
+ not RNS.Transport.has_path(destination_hash_bytes)
+ and time.time() < deadline
+ ):
await asyncio.sleep(0.1)
return RNS.Transport.has_path(destination_hash_bytes)
@@ -14278,7 +14513,8 @@ class ReticulumMeshChat:
if sender_identity_hash is not None:
if (
ctx.forwarding_manager
- and sender_identity_hash in ctx.forwarding_manager.forwarding_destinations
+ and sender_identity_hash
+ in ctx.forwarding_manager.forwarding_destinations
):
source_destination = ctx.forwarding_manager.forwarding_destinations[
sender_identity_hash

diff --git a/meshchatx/src/backend/async_utils.py b/meshchatx/src/backend/async_utils.py
index 86364b32..23bb5bc1 100644
--- a/meshchatx/src/backend/async_utils.py
+++ b/meshchatx/src/backend/async_utils.py
@@ -71,7 +71,10 @@ class AsyncUtils:
)
with AsyncUtils._futures_lock:
AsyncUtils._pending_futures.append(future)
- if len(AsyncUtils._pending_futures) >= AsyncUtils._FUTURES_SWEEP_THRESHOLD:
+ if (
+ len(AsyncUtils._pending_futures)
+ >= AsyncUtils._FUTURES_SWEEP_THRESHOLD
+ ):
AsyncUtils._pending_futures = [
f for f in AsyncUtils._pending_futures if not f.done()
]

diff --git a/meshchatx/src/backend/audio_codec.py b/meshchatx/src/backend/audio_codec.py
index ec65a7ae..4ed86bf9 100644
--- a/meshchatx/src/backend/audio_codec.py
+++ b/meshchatx/src/backend/audio_codec.py
@@ -79,9 +79,13 @@ def _decode_with_wave(data: bytes):
if sample_width == 2:
samples = np.frombuffer(raw, dtype=np.int16).astype(np.float32) / 32768.0
elif sample_width == 1:
- samples = (np.frombuffer(raw, dtype=np.uint8).astype(np.float32) - 128.0) / 128.0
+ samples = (
+ np.frombuffer(raw, dtype=np.uint8).astype(np.float32) - 128.0
+ ) / 128.0
elif sample_width == 4:
- samples = np.frombuffer(raw, dtype=np.int32).astype(np.float32) / 2147483648.0
+ samples = (
+ np.frombuffer(raw, dtype=np.int32).astype(np.float32) / 2147483648.0
+ )
else:
return None
@@ -109,7 +113,9 @@ def _decode_with_miniaudio(data: bytes):
return None
if decoded.num_frames <= 0 or decoded.nchannels <= 0:
return None
- samples = np.frombuffer(decoded.samples, dtype=np.int16).astype(np.float32) / 32768.0
+ samples = (
+ np.frombuffer(decoded.samples, dtype=np.int16).astype(np.float32) / 32768.0
+ )
return DecodedAudio(
samples=samples.reshape(-1, decoded.nchannels),
samplerate=decoded.sample_rate,

diff --git a/meshchatx/src/backend/auto_propagation_manager.py b/meshchatx/src/backend/auto_propagation_manager.py
index b6d0b761..d9b1c9ad 100644
--- a/meshchatx/src/backend/auto_propagation_manager.py
+++ b/meshchatx/src/backend/auto_propagation_manager.py
@@ -134,7 +134,9 @@ class AutoPropagationManager:
if not sorted_candidates:
return
- previous_hex = self.config.lxmf_preferred_propagation_node_destination_hash.get()
+ previous_hex = (
+ self.config.lxmf_preferred_propagation_node_destination_hash.get()
+ )
ordered: list[tuple[int, str]] = []
seen_hex: set[str] = set()
if previous_hex and previous_hex in best_by_hex:

diff --git a/meshchatx/src/backend/bot_handler.py b/meshchatx/src/backend/bot_handler.py
index 984cdfc6..47bcf2a0 100644
--- a/meshchatx/src/backend/bot_handler.py
+++ b/meshchatx/src/backend/bot_handler.py
@@ -147,10 +147,16 @@ class BotHandler:
# Try running instance first
instance = self.running_bots.get(bot_id, {}).get("instance")
- if instance and getattr(instance, "bot", None) and getattr(instance.bot, "local", None):
+ if (
+ instance
+ and getattr(instance, "bot", None)
+ and getattr(instance.bot, "local", None)
+ ):
with contextlib.suppress(Exception):
lh = instance.bot.local.hash
- address_full = lh.hex() if isinstance(lh, (bytes, bytearray)) else None
+ address_full = (
+ lh.hex() if isinstance(lh, (bytes, bytearray)) else None
+ )
if address_full:
address_full = self._normalize_lxmf_hash_hex(address_full)
if address_full:
@@ -164,7 +170,9 @@ class BotHandler:
destination = RNS.Destination(identity, "lxmf", "delivery")
address_full = self._normalize_lxmf_hash_hex(destination.hash)
if address_full:
- address_pretty = RNS.prettyhexrep(bytes.fromhex(address_full))
+ address_pretty = RNS.prettyhexrep(
+ bytes.fromhex(address_full)
+ )
if address_full is None:
address_full = self._read_lxmf_address_sidecar(entry.get("storage_dir"))

diff --git a/meshchatx/src/backend/bot_process.py b/meshchatx/src/backend/bot_process.py
index 92052899..fd3fc650 100644
--- a/meshchatx/src/backend/bot_process.py
+++ b/meshchatx/src/backend/bot_process.py
@@ -60,7 +60,9 @@ def main():
else:
config_path = os.path.join(os.path.abspath(args.storage), "config")
os.makedirs(config_path, exist_ok=True)
- reticulum_config_dir = os.path.abspath(os.path.expanduser(args.reticulum_config_dir))
+ reticulum_config_dir = os.path.abspath(
+ os.path.expanduser(args.reticulum_config_dir)
+ )
os.makedirs(reticulum_config_dir, exist_ok=True)
BotCls = TEMPLATE_MAP[args.template]

diff --git a/meshchatx/src/backend/bot_templates.py b/meshchatx/src/backend/bot_templates.py
index 7edac8d2..be6d0897 100644
--- a/meshchatx/src/backend/bot_templates.py
+++ b/meshchatx/src/backend/bot_templates.py
@@ -162,17 +162,23 @@ class NoteBotTemplate(StoppableBot):
if not ctx.args:
response = "Your Notes:\n"
for i, note in enumerate(notes[-10:], 1):
- tags = " ".join(f"#{tag}" for tag in note["tags"]) if note["tags"] else ""
+ tags = (
+ " ".join(f"#{tag}" for tag in note["tags"])
+ if note["tags"]
+ else ""
+ )
response += f"{i}. {note['text']} {tags}\n"
if len(notes) > 10:
- response += (
- f"\nShowing last 10 of {len(notes)} notes. Use /notes all to see all."
- )
+ response += f"\nShowing last 10 of {len(notes)} notes. Use /notes all to see all."
ctx.reply(response)
elif ctx.args[0] == "all":
response = "All Your Notes:\n"
for i, note in enumerate(notes, 1):
- tags = " ".join(f"#{tag}" for tag in note["tags"]) if note["tags"] else ""
+ tags = (
+ " ".join(f"#{tag}" for tag in note["tags"])
+ if note["tags"]
+ else ""
+ )
response += f"{i}. {note['text']} {tags}\n"
ctx.reply(response)

diff --git a/meshchatx/src/backend/config_manager.py b/meshchatx/src/backend/config_manager.py
index 211cbc2c..9f213f59 100644
--- a/meshchatx/src/backend/config_manager.py
+++ b/meshchatx/src/backend/config_manager.py
@@ -66,10 +66,12 @@ class ConfigManager:
"lxmf_preferred_propagation_node_auto_select",
False,
)
- self.lxmf_preferred_propagation_node_auto_sync_interval_seconds = self.IntConfig(
- self,
- "lxmf_preferred_propagation_node_auto_sync_interval_seconds",
- 0,
+ self.lxmf_preferred_propagation_node_auto_sync_interval_seconds = (
+ self.IntConfig(
+ self,
+ "lxmf_preferred_propagation_node_auto_sync_interval_seconds",
+ 0,
+ )
)
self.lxmf_preferred_propagation_node_last_synced_at = self.IntConfig(
self,

diff --git a/meshchatx/src/backend/database/__init__.py b/meshchatx/src/backend/database/__init__.py
index afc8640e..ea1d3e0c 100644
--- a/meshchatx/src/backend/database/__init__.py
+++ b/meshchatx/src/backend/database/__init__.py
@@ -180,7 +180,9 @@ class Database:
_log.warning("DB open health check: no result")
else:
first = integrity_rows[0]
- val = next(iter(first.values())) if isinstance(first, dict) else first[0]
+ val = (
+ next(iter(first.values())) if isinstance(first, dict) else first[0]
+ )
if val != "ok":
issues.append(f"Database integrity check failed: {val!s}")
_log.warning("DB open health check: %s", val)
@@ -227,7 +229,9 @@ class Database:
_log.warning("DB close health check: no result")
else:
first = integrity_rows[0]
- val = next(iter(first.values())) if isinstance(first, dict) else first[0]
+ val = (
+ next(iter(first.values())) if isinstance(first, dict) else first[0]
+ )
if val != "ok":
issues.append(f"Database integrity check failed: {val!s}")
_log.warning("DB close health check: integrity failed")
@@ -265,7 +269,9 @@ class Database:
page_size = self._get_pragma_value("page_size", 0) or 0
page_count = self._get_pragma_value("page_count", 0) or 0
freelist_pages = self._get_pragma_value("freelist_count", 0) or 0
- freelist_bytes = page_size * freelist_pages if page_size > 0 and freelist_pages > 0 else 0
+ freelist_bytes = (
+ page_size * freelist_pages if page_size > 0 and freelist_pages > 0 else 0
+ )
if freelist_bytes > 0:
free_bytes = freelist_bytes
else:

diff --git a/meshchatx/src/backend/database/gifs.py b/meshchatx/src/backend/database/gifs.py
index e3968199..4c91ae56 100644
--- a/meshchatx/src/backend/database/gifs.py
+++ b/meshchatx/src/backend/database/gifs.py
@@ -219,7 +219,10 @@ class UserGifsDAO:
(identity_hash, ch),
)
- if self.count_for_identity(identity_hash) >= gif_utils.MAX_GIFS_PER_IDENTITY:
+ if (
+ self.count_for_identity(identity_hash)
+ >= gif_utils.MAX_GIFS_PER_IDENTITY
+ ):
errors.append("gif_limit_reached")
break

diff --git a/meshchatx/src/backend/database/legacy_migrator.py b/meshchatx/src/backend/database/legacy_migrator.py
index 3c9d3b27..bce33312 100644
--- a/meshchatx/src/backend/database/legacy_migrator.py
+++ b/meshchatx/src/backend/database/legacy_migrator.py
@@ -104,9 +104,7 @@ class LegacyMigrator:
try:
# Check if table exists in legacy DB
# We use a f-string here for the alias and table name, which are controlled by us
- check_query = (
- f"SELECT name FROM {alias}.sqlite_master WHERE type='table' AND name=?"
- )
+ check_query = f"SELECT name FROM {alias}.sqlite_master WHERE type='table' AND name=?"
res = self.provider.fetchone(check_query, (table,))
if res:

diff --git a/meshchatx/src/backend/database/misc.py b/meshchatx/src/backend/database/misc.py
index 94dc94cf..7b34335f 100644
--- a/meshchatx/src/backend/database/misc.py
+++ b/meshchatx/src/backend/database/misc.py
@@ -177,7 +177,9 @@ class MiscDAO:
params.append(destination_hash)
if query:
like_term = f"%{query}%"
- sql += " AND (destination_hash LIKE ? OR page_path LIKE ? OR content LIKE ?)"
+ sql += (
+ " AND (destination_hash LIKE ? OR page_path LIKE ? OR content LIKE ?)"
+ )
params.extend([like_term, like_term, like_term])
sql += " ORDER BY created_at DESC"

diff --git a/meshchatx/src/backend/database/provider.py b/meshchatx/src/backend/database/provider.py
index 30d021cb..af40695a 100644
--- a/meshchatx/src/backend/database/provider.py
+++ b/meshchatx/src/backend/database/provider.py
@@ -74,10 +74,13 @@ class DatabaseProvider:
if isinstance(params, dict):
params = {
- k: (v.isoformat() if isinstance(v, datetime) else v) for k, v in params.items()
+ k: (v.isoformat() if isinstance(v, datetime) else v)
+ for k, v in params.items()
}
else:
- params = tuple((p.isoformat() if isinstance(p, datetime) else p) for p in params)
+ params = tuple(
+ (p.isoformat() if isinstance(p, datetime) else p) for p in params
+ )
if params:
cursor.execute(query, params)

diff --git a/meshchatx/src/backend/database/ringtones.py b/meshchatx/src/backend/database/ringtones.py
index 0395a19b..aa540ae8 100644
--- a/meshchatx/src/backend/database/ringtones.py
+++ b/meshchatx/src/backend/database/ringtones.py
@@ -29,7 +29,9 @@ class RingtoneDAO:
display_name = filename
# check if this is the first ringtone, if so make it primary
- count = self.provider.fetchone("SELECT COUNT(*) as count FROM ringtones")["count"]
+ count = self.provider.fetchone("SELECT COUNT(*) as count FROM ringtones")[
+ "count"
+ ]
is_primary = 1 if count == 0 else 0
cursor = self.provider.execute(

diff --git a/meshchatx/src/backend/database/sticker_packs.py b/meshchatx/src/backend/database/sticker_packs.py
index 20843030..dedc445b 100644
--- a/meshchatx/src/backend/database/sticker_packs.py
+++ b/meshchatx/src/backend/database/sticker_packs.py
@@ -81,7 +81,10 @@ class UserStickerPacksDAO:
is_strict: bool = True,
) -> dict:
"""Create a new pack. Raises ``ValueError`` on quota or short_name clash."""
- if self.count_for_identity(identity_hash) >= sticker_utils.MAX_STICKER_PACKS_PER_IDENTITY:
+ if (
+ self.count_for_identity(identity_hash)
+ >= sticker_utils.MAX_STICKER_PACKS_PER_IDENTITY
+ ):
msg = "pack_limit_reached"
raise ValueError(msg)
sn = sticker_pack_utils.sanitize_pack_short_name(short_name)
@@ -150,7 +153,11 @@ class UserStickerPacksDAO:
if pack_type is not None
else existing["pack_type"]
)
- new_cover = existing["cover_sticker_id"] if cover_sticker_id is ... else cover_sticker_id
+ new_cover = (
+ existing["cover_sticker_id"]
+ if cover_sticker_id is ...
+ else cover_sticker_id
+ )
cur = self.provider.execute(
"""
UPDATE user_sticker_packs

diff --git a/meshchatx/src/backend/database/stickers.py b/meshchatx/src/backend/database/stickers.py
index c5cdfb1f..15c641ab 100644
--- a/meshchatx/src/backend/database/stickers.py
+++ b/meshchatx/src/backend/database/stickers.py
@@ -187,7 +187,10 @@ class UserStickersDAO:
metadata so the picker can render the sticker correctly without
re-parsing.
"""
- if self.count_for_identity(identity_hash) >= sticker_utils.MAX_STICKERS_PER_IDENTITY:
+ if (
+ self.count_for_identity(identity_hash)
+ >= sticker_utils.MAX_STICKERS_PER_IDENTITY
+ ):
msg = "sticker_limit_reached"
raise ValueError(msg)
@@ -345,7 +348,10 @@ class UserStickersDAO:
(identity_hash, ch),
)
- if self.count_for_identity(identity_hash) >= sticker_utils.MAX_STICKERS_PER_IDENTITY:
+ if (
+ self.count_for_identity(identity_hash)
+ >= sticker_utils.MAX_STICKERS_PER_IDENTITY
+ ):
errors.append("sticker_limit_reached")
break

diff --git a/meshchatx/src/backend/docs_manager.py b/meshchatx/src/backend/docs_manager.py
index 6fe9c9d9..1b859a1a 100644
--- a/meshchatx/src/backend/docs_manager.py
+++ b/meshchatx/src/backend/docs_manager.py
@@ -264,7 +264,9 @@ class DocsManager:
def has_meshchatx_docs(self):
return (
- any(f.endswith((".md", ".txt")) for f in os.listdir(self.meshchatx_docs_dir))
+ any(
+ f.endswith((".md", ".txt")) for f in os.listdir(self.meshchatx_docs_dir)
+ )
if os.path.exists(self.meshchatx_docs_dir)
else False
)

diff --git a/meshchatx/src/backend/forwarding_manager.py b/meshchatx/src/backend/forwarding_manager.py
index 963d06c0..0577363c 100644
--- a/meshchatx/src/backend/forwarding_manager.py
+++ b/meshchatx/src/backend/forwarding_manager.py
@@ -144,7 +144,10 @@ class ForwardingManager:
for link in list(RNS.Transport.active_links):
match = False
if hasattr(link, "destination") and link.destination:
- if hasattr(link.destination, "identity") and link.destination.identity:
+ if (
+ hasattr(link.destination, "identity")
+ and link.destination.identity
+ ):
if link.destination.identity.hash == ih:
match = True
if match:

diff --git a/meshchatx/src/backend/identity_context.py b/meshchatx/src/backend/identity_context.py
index 62289015..9e342241 100644
--- a/meshchatx/src/backend/identity_context.py
+++ b/meshchatx/src/backend/identity_context.py
@@ -158,7 +158,10 @@ class IdentityContext:
self.config = ConfigManager(self.database)
# Apply overrides from CLI/ENV if provided
- if hasattr(self.app, "gitea_base_url_override") and self.app.gitea_base_url_override:
+ if (
+ hasattr(self.app, "gitea_base_url_override")
+ and self.app.gitea_base_url_override
+ ):
self.config.gitea_base_url.set(self.app.gitea_base_url_override)
self.message_handler = MessageHandler(self.database)
@@ -235,7 +238,9 @@ class IdentityContext:
# Restore preferred propagation node on startup
with contextlib.suppress(Exception):
- preferred_node = self.config.lxmf_preferred_propagation_node_destination_hash.get()
+ preferred_node = (
+ self.config.lxmf_preferred_propagation_node_destination_hash.get()
+ )
if preferred_node:
self.app.set_active_propagation_node(preferred_node, context=self)
@@ -284,7 +289,9 @@ class IdentityContext:
storage_dir=self.storage_path,
db=self.database,
)
- self.telephone_manager.get_name_for_identity_hash = self.app.get_name_for_identity_hash
+ self.telephone_manager.get_name_for_identity_hash = (
+ self.app.get_name_for_identity_hash
+ )
self.telephone_manager.on_initiation_status_callback = lambda status, target: (
self.app.on_telephone_initiation_status(
status,
@@ -312,7 +319,9 @@ class IdentityContext:
telephone_manager=self.telephone_manager,
storage_dir=self.storage_path,
)
- self.voicemail_manager.get_name_for_identity_hash = self.app.get_name_for_identity_hash
+ self.voicemail_manager.get_name_for_identity_hash = (
+ self.app.get_name_for_identity_hash
+ )
self.voicemail_manager.on_new_voicemail_callback = lambda vm: (
self.app.on_new_voicemail_received(vm, context=self)
)
@@ -356,7 +365,9 @@ class IdentityContext:
# start background thread for auto syncing propagation nodes
thread = threading.Thread(
target=asyncio.run,
- args=(self.app.announce_sync_propagation_nodes(self.session_id, context=self),),
+ args=(
+ self.app.announce_sync_propagation_nodes(self.session_id, context=self),
+ ),
)
thread.daemon = True
thread.start()
@@ -419,24 +430,28 @@ class IdentityContext:
),
AnnounceHandler(
"lxmf.propagation",
- lambda aspect, dh, ai, ad, aph: self.app.on_lxmf_propagation_announce_received(
- aspect,
- dh,
- ai,
- ad,
- aph,
- context=self,
+ lambda aspect, dh, ai, ad, aph: (
+ self.app.on_lxmf_propagation_announce_received(
+ aspect,
+ dh,
+ ai,
+ ad,
+ aph,
+ context=self,
+ )
),
),
AnnounceHandler(
"nomadnetwork.node",
- lambda aspect, dh, ai, ad, aph: self.app.on_nomadnet_node_announce_received(
- aspect,
- dh,
- ai,
- ad,
- aph,
- context=self,
+ lambda aspect, dh, ai, ad, aph: (
+ self.app.on_nomadnet_node_announce_received(
+ aspect,
+ dh,
+ ai,
+ ad,
+ aph,
+ context=self,
+ )
),
),
]

diff --git a/meshchatx/src/backend/identity_manager.py b/meshchatx/src/backend/identity_manager.py
index 617dac3f..f3826a24 100644
--- a/meshchatx/src/backend/identity_manager.py
+++ b/meshchatx/src/backend/identity_manager.py
@@ -148,7 +148,8 @@ class IdentityManager:
"lxmf_address": lxmf_address,
"lxst_address": lxst_address,
"is_current": (
- current_identity_hash is not None and identity_hash == current_identity_hash
+ current_identity_hash is not None
+ and identity_hash == current_identity_hash
),
},
)

diff --git a/meshchatx/src/backend/integrity_manager.py b/meshchatx/src/backend/integrity_manager.py
index b032d41f..a9f4bee8 100644
--- a/meshchatx/src/backend/integrity_manager.py
+++ b/meshchatx/src/backend/integrity_manager.py
@@ -47,7 +47,10 @@ class IntegrityManager:
# to avoid accidentally ignoring important files with similar names.
if "lxmf_router" in path_parts:
# Added more volatile LXMF patterns
- if any(part in ["announces", "storage", "identities", "tmp"] for part in path_parts):
+ if any(
+ part in ["announces", "storage", "identities", "tmp"]
+ for part in path_parts
+ ):
return True
# Specifically ignore stamp costs which are frequently updated
@@ -154,7 +157,10 @@ class IntegrityManager:
actual_entropy = self._calculate_entropy(self.database_path)
saved_entropy = manifest_metadata.get(db_rel, {}).get("entropy")
- if saved_entropy is not None and abs(actual_entropy - saved_entropy) > 1.0:
+ if (
+ saved_entropy is not None
+ and abs(actual_entropy - saved_entropy) > 1.0
+ ):
issues.append(
f"Database structural anomaly (Entropy Δ: {abs(actual_entropy - saved_entropy):.2f})",
)
@@ -190,7 +196,9 @@ class IntegrityManager:
)
actual_size = full_path.stat().st_size
- is_critical = any(c in rel_path for c in ["identity", "config"])
+ is_critical = any(
+ c in rel_path for c in ["identity", "config"]
+ )
if is_critical:
issues.append(

diff --git a/meshchatx/src/backend/interfaces/WebsocketServerInterface.py b/meshchatx/src/backend/interfaces/WebsocketServerInterface.py
index f8a7184f..2b7a548e 100644
--- a/meshchatx/src/backend/interfaces/WebsocketServerInterface.py
+++ b/meshchatx/src/backend/interfaces/WebsocketServerInterface.py
@@ -18,7 +18,9 @@ class WebsocketServerInterface(Interface):
RESTART_DELAY_SECONDS = 5
def __str__(self):
- return f"WebsocketServerInterface[{self.name}/{self.listen_ip}:{self.listen_port}]"
+ return (
+ f"WebsocketServerInterface[{self.name}/{self.listen_ip}:{self.listen_port}]"
+ )
def __init__(self, owner, configuration):
super().__init__()

diff --git a/meshchatx/src/backend/lxmf_utils.py b/meshchatx/src/backend/lxmf_utils.py
index eac38601..291e2d08 100644
--- a/meshchatx/src/backend/lxmf_utils.py
+++ b/meshchatx/src/backend/lxmf_utils.py
@@ -70,13 +70,17 @@ def is_user_facing_lxmf_payload(fields, content, title) -> bool:
return True
image = fields.get("image")
- if isinstance(image, dict) and (image.get("image_size") or image.get("image_bytes")):
+ if isinstance(image, dict) and (
+ image.get("image_size") or image.get("image_bytes")
+ ):
return True
if image is None and fields.get(LXMF_IMAGE_FIELD) is not None:
return True
audio = fields.get("audio")
- if isinstance(audio, dict) and (audio.get("audio_size") or audio.get("audio_bytes")):
+ if isinstance(audio, dict) and (
+ audio.get("audio_size") or audio.get("audio_bytes")
+ ):
return True
if audio is None and fields.get(LXMF_AUDIO_FIELD) is not None:
return True
@@ -110,7 +114,10 @@ def convert_lxmf_message_to_dict(
if field_type == LXMF.FIELD_FILE_ATTACHMENTS and isinstance(value, list):
file_attachments = []
for file_attachment in value:
- if not isinstance(file_attachment, (list, tuple)) or len(file_attachment) < 2:
+ if (
+ not isinstance(file_attachment, (list, tuple))
+ or len(file_attachment) < 2
+ ):
continue
file_name = file_attachment[0]
file_data = file_attachment[1]
@@ -133,7 +140,11 @@ def convert_lxmf_message_to_dict(
fields["file_attachments"] = file_attachments
# handle image field
- if field_type == LXMF.FIELD_IMAGE and isinstance(value, (list, tuple)) and len(value) >= 2:
+ if (
+ field_type == LXMF.FIELD_IMAGE
+ and isinstance(value, (list, tuple))
+ and len(value) >= 2
+ ):
image_type = value[0]
image_data = value[1]
if isinstance(image_data, (bytes, bytearray)):
@@ -148,7 +159,11 @@ def convert_lxmf_message_to_dict(
}
# handle audio field
- if field_type == LXMF.FIELD_AUDIO and isinstance(value, (list, tuple)) and len(value) >= 2:
+ if (
+ field_type == LXMF.FIELD_AUDIO
+ and isinstance(value, (list, tuple))
+ and len(value) >= 2
+ ):
audio_mode = value[0]
audio_data = value[1]
if isinstance(audio_data, (bytes, bytearray)):
@@ -196,7 +211,9 @@ def convert_lxmf_message_to_dict(
fields["reply_to"] = value.hex() if isinstance(value, bytes) else value
if field_type == 0x31:
fields["reply_quoted_content"] = (
- value.decode("utf-8", errors="replace") if isinstance(value, bytes) else value
+ value.decode("utf-8", errors="replace")
+ if isinstance(value, bytes)
+ else value
)
if field_type == LXMF_APP_EXTENSIONS_FIELD and isinstance(value, dict):
@@ -231,7 +248,11 @@ def convert_lxmf_message_to_dict(
val = message_fields[0x30]
reply_to_hash = val.hex() if isinstance(val, bytes) else val
- content = lxmf_message.content.decode("utf-8", errors="replace") if lxmf_message.content else ""
+ content = (
+ lxmf_message.content.decode("utf-8", errors="replace")
+ if lxmf_message.content
+ else ""
+ )
# auto-detect reply from content if not present
if not reply_to_hash and content and isinstance(content, str):
@@ -255,7 +276,9 @@ def convert_lxmf_message_to_dict(
"next_delivery_attempt",
None,
), # attribute may not exist yet
- "title": lxmf_message.title.decode("utf-8", errors="replace") if lxmf_message.title else "",
+ "title": lxmf_message.title.decode("utf-8", errors="replace")
+ if lxmf_message.title
+ else "",
"content": content,
"fields": fields,
"timestamp": lxmf_message.timestamp,

diff --git a/meshchatx/src/backend/map_manager.py b/meshchatx/src/backend/map_manager.py
index 671eab60..65dfd813 100644
--- a/meshchatx/src/backend/map_manager.py
+++ b/meshchatx/src/backend/map_manager.py
@@ -315,7 +315,9 @@ class MapManager:
)
return None
- tasks = [asyncio.create_task(download_tile(tile)) for tile in tiles_to_download]
+ tasks = [
+ asyncio.create_task(download_tile(tile)) for tile in tiles_to_download
+ ]
for coro in asyncio.as_completed(tasks):
if export_id in self._export_cancelled:
@@ -337,7 +339,9 @@ class MapManager:
(current_count / total_tiles) * 100,
)
- if len(batch_data) >= batch_size or (current_count == total_tiles and batch_data):
+ if len(batch_data) >= batch_size or (
+ current_count == total_tiles and batch_data
+ ):
try:
cursor.executemany(
"INSERT INTO tiles VALUES (?, ?, ?, ?)",
@@ -354,7 +358,9 @@ class MapManager:
n = 2.0**zoom
x = int((lon + 180.0) / 360.0 * n)
y = int(
- (1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n,
+ (1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi)
+ / 2.0
+ * n,
)
return x, y

diff --git a/meshchatx/src/backend/meshchat_utils.py b/meshchatx/src/backend/meshchat_utils.py
index bfeda506..9f1e232b 100644
--- a/meshchatx/src/backend/meshchat_utils.py
+++ b/meshchatx/src/backend/meshchat_utils.py
@@ -136,9 +136,9 @@ def parse_lxmf_display_name(
# Try manual parsing first to avoid LXMF library call.
if len(app_data_bytes) > 0:
- if (app_data_bytes[0] >= 0x90 and app_data_bytes[0] <= 0x9F) or app_data_bytes[
- 0
- ] == 0xDC:
+ if (
+ app_data_bytes[0] >= 0x90 and app_data_bytes[0] <= 0x9F
+ ) or app_data_bytes[0] == 0xDC:
with contextlib.suppress(Exception):
peer_data = msgpack.unpackb(app_data_bytes)
if isinstance(peer_data, list) and len(peer_data) >= 1:

diff --git a/meshchatx/src/backend/nomadnet_downloader.py b/meshchatx/src/backend/nomadnet_downloader.py
index 737e5898..3d750532 100644
--- a/meshchatx/src/backend/nomadnet_downloader.py
+++ b/meshchatx/src/backend/nomadnet_downloader.py
@@ -36,7 +36,11 @@ def get_cached_active_link(destination_hash: bytes):
def sweep_stale_links():
"""Evict all non-ACTIVE links from the global cache."""
with _nomadnet_links_lock:
- stale = [k for k, v in nomadnet_cached_links.items() if v.status is not RNS.Link.ACTIVE]
+ stale = [
+ k
+ for k, v in nomadnet_cached_links.items()
+ if v.status is not RNS.Link.ACTIVE
+ ]
for k in stale:
del nomadnet_cached_links[k]
@@ -181,7 +185,9 @@ class NomadnetDownloader:
timeout_after_seconds = time.time() + link_establishment_timeout
- while link.status is not RNS.Link.ACTIVE and time.time() < timeout_after_seconds:
+ while (
+ link.status is not RNS.Link.ACTIVE and time.time() < timeout_after_seconds
+ ):
if self.is_cancelled:
return
await asyncio.sleep(_POLL_INTERVAL_S)
@@ -301,7 +307,11 @@ class NomadnetFileDownloader(NomadnetDownloader):
self.on_file_download_success(file_name, file_data)
return
- if isinstance(response, list) and len(response) > 1 and isinstance(response[1], dict):
+ if (
+ isinstance(response, list)
+ and len(response) > 1
+ and isinstance(response[1], dict)
+ ):
file_data: bytes = response[0]
metadata: dict = response[1]

diff --git a/meshchatx/src/backend/page_node.py b/meshchatx/src/backend/page_node.py
index 55d436e8..7545e4e6 100644
--- a/meshchatx/src/backend/page_node.py
+++ b/meshchatx/src/backend/page_node.py
@@ -336,7 +336,8 @@ class PageNode:
return sorted(
f
for f in os.listdir(self.pages_dir)
- if os.path.isfile(os.path.join(self.pages_dir, f)) and is_allowed_page_filename(f)
+ if os.path.isfile(os.path.join(self.pages_dir, f))
+ and is_allowed_page_filename(f)
)
def get_page_content(self, name):

diff --git a/meshchatx/src/backend/persistent_log_handler.py b/meshchatx/src/backend/persistent_log_handler.py
index b95059e7..5c86a603 100644
--- a/meshchatx/src/backend/persistent_log_handler.py
+++ b/meshchatx/src/backend/persistent_log_handler.py
@@ -64,7 +64,9 @@ class PersistentLogHandler(logging.Handler):
self._error_events.append(now_mono)
# Periodically flush to database if available
- if self.database and (time.time() - self.last_flush_time > self.flush_interval):
+ if self.database and (
+ time.time() - self.last_flush_time > self.flush_interval
+ ):
self._flush_to_db()
except Exception:
@@ -226,7 +228,9 @@ class PersistentLogHandler(logging.Handler):
if level:
logs = [log for log in logs if log["level"] == level]
if is_anomaly is not None:
- logs = [log for log in logs if log["is_anomaly"] == (1 if is_anomaly else 0)]
+ logs = [
+ log for log in logs if log["is_anomaly"] == (1 if is_anomaly else 0)
+ ]
# Sort descending
logs.sort(key=lambda x: x["timestamp"], reverse=True)

diff --git a/meshchatx/src/backend/recovery/crash_recovery.py b/meshchatx/src/backend/recovery/crash_recovery.py
index 625bbf03..74184e77 100644
--- a/meshchatx/src/backend/recovery/crash_recovery.py
+++ b/meshchatx/src/backend/recovery/crash_recovery.py
@@ -383,7 +383,9 @@ class CrashRecovery:
"no_table_config": "no such table: config" in error_msg,
"in_memory_db": diagnosis.get("db_type") == "memory",
"corrupt_in_msg": "corrupt" in error_msg or "malformed" in error_msg,
- "async_in_msg": any(x in error_msg for x in ["asyncio", "event loop", "runtimeerror"]),
+ "async_in_msg": any(
+ x in error_msg for x in ["asyncio", "event loop", "runtimeerror"]
+ ),
"no_loop_in_msg": "no current event loop" in error_msg
or "no running event loop" in error_msg,
"low_mem": diagnosis.get("low_memory", False),
@@ -392,7 +394,8 @@ class CrashRecovery:
"lxmf_in_msg": "lxmf" in error_msg or "lxmr" in error_msg,
"identity_in_msg": "identity" in error_msg or "private key" in error_msg,
"no_interfaces": diagnosis.get("active_interfaces", 0) == 0,
- "old_python": py_version.major < 3 or (py_version.major == 3 and py_version.minor < 10),
+ "old_python": py_version.major < 3
+ or (py_version.major == 3 and py_version.minor < 10),
"legacy_kernel": "linux" in platform.system().lower()
and (
(_m := re.search(r"(\d+\.\d+)", platform.release())) is not None

diff --git a/meshchatx/src/backend/rncp_handler.py b/meshchatx/src/backend/rncp_handler.py
index 81202520..fb095a01 100644
--- a/meshchatx/src/backend/rncp_handler.py
+++ b/meshchatx/src/backend/rncp_handler.py
@@ -178,7 +178,9 @@ class RNCPHandler:
if transfer_id in self.active_transfers:
self.active_transfers[transfer_id]["status"] = "completed"
- self.active_transfers[transfer_id]["saved_path"] = saved_filename
+ self.active_transfers[transfer_id]["saved_path"] = (
+ saved_filename
+ )
self.active_transfers[transfer_id]["filename"] = filename
self._emit_receive_event(
{
@@ -277,7 +279,9 @@ class RNCPHandler:
RNS.Transport.request_path(destination_hash)
timeout_after = time.time() + timeout
- while not RNS.Transport.has_path(destination_hash) and time.time() < timeout_after:
+ while (
+ not RNS.Transport.has_path(destination_hash) and time.time() < timeout_after
+ ):
await asyncio.sleep(0.1)
if not RNS.Transport.has_path(destination_hash):
@@ -369,7 +373,9 @@ class RNCPHandler:
RNS.Transport.request_path(destination_hash)
timeout_after = time.time() + timeout
- while not RNS.Transport.has_path(destination_hash) and time.time() < timeout_after:
+ while (
+ not RNS.Transport.has_path(destination_hash) and time.time() < timeout_after
+ ):
await asyncio.sleep(0.1)
if not RNS.Transport.has_path(destination_hash):

diff --git a/meshchatx/src/backend/rnpath_handler.py b/meshchatx/src/backend/rnpath_handler.py
index 94fda110..5ce208ee 100644
--- a/meshchatx/src/backend/rnpath_handler.py
+++ b/meshchatx/src/backend/rnpath_handler.py
@@ -71,10 +71,18 @@ class RNPathHandler:
total = len(formatted_table)
responsive_count = len(
- [e for e in formatted_table if e["state"] == RNS.Transport.STATE_RESPONSIVE],
+ [
+ e
+ for e in formatted_table
+ if e["state"] == RNS.Transport.STATE_RESPONSIVE
+ ],
)
unresponsive_count = len(
- [e for e in formatted_table if e["state"] == RNS.Transport.STATE_UNRESPONSIVE],
+ [
+ e
+ for e in formatted_table
+ if e["state"] == RNS.Transport.STATE_UNRESPONSIVE
+ ],
)
# Pagination

diff --git a/meshchatx/src/backend/rnpath_trace_handler.py b/meshchatx/src/backend/rnpath_trace_handler.py
index 9b3215c6..44d6a018 100644
--- a/meshchatx/src/backend/rnpath_trace_handler.py
+++ b/meshchatx/src/backend/rnpath_trace_handler.py
@@ -51,7 +51,11 @@ class RNPathTraceHandler:
local_hash = "unknown"
if self.identity and hasattr(self.identity, "hash"):
local_hash = self.identity.hash.hex()
- elif self.reticulum and hasattr(self.reticulum, "identity") and self.reticulum.identity:
+ elif (
+ self.reticulum
+ and hasattr(self.reticulum, "identity")
+ and self.reticulum.identity
+ ):
local_hash = self.reticulum.identity.hash.hex()
path.append({"type": "local", "hash": local_hash, "name": "Local Node"})

diff --git a/meshchatx/src/backend/rnprobe_handler.py b/meshchatx/src/backend/rnprobe_handler.py
index 89440445..4f49892b 100644
--- a/meshchatx/src/backend/rnprobe_handler.py
+++ b/meshchatx/src/backend/rnprobe_handler.py
@@ -34,9 +34,13 @@ class RNProbeHandler:
RNS.Transport.request_path(destination_hash)
timeout_after = time.time() + (
- timeout or self.DEFAULT_TIMEOUT + self.reticulum.get_first_hop_timeout(destination_hash)
+ timeout
+ or self.DEFAULT_TIMEOUT
+ + self.reticulum.get_first_hop_timeout(destination_hash)
)
- while not RNS.Transport.has_path(destination_hash) and time.time() < timeout_after:
+ while (
+ not RNS.Transport.has_path(destination_hash) and time.time() < timeout_after
+ ):
await asyncio.sleep(0.1)
if not RNS.Transport.has_path(destination_hash):
@@ -79,9 +83,12 @@ class RNProbeHandler:
timeout_after = time.time() + (
timeout
- or self.DEFAULT_TIMEOUT + self.reticulum.get_first_hop_timeout(destination_hash)
+ or self.DEFAULT_TIMEOUT
+ + self.reticulum.get_first_hop_timeout(destination_hash)
)
- while receipt.status == RNS.PacketReceipt.SENT and time.time() < timeout_after:
+ while (
+ receipt.status == RNS.PacketReceipt.SENT and time.time() < timeout_after
+ ):
await asyncio.sleep(0.1)
result: dict = {

diff --git a/meshchatx/src/backend/rnstatus_handler.py b/meshchatx/src/backend/rnstatus_handler.py
index fea92585..d962710c 100644
--- a/meshchatx/src/backend/rnstatus_handler.py
+++ b/meshchatx/src/backend/rnstatus_handler.py
@@ -196,7 +196,11 @@ class RNStatusHandler:
name = ifstat.get("name", "")
if name.startswith(
- ("LocalInterface[", "TCPInterface[Client", "BackboneInterface[Client on")
+ (
+ "LocalInterface[",
+ "TCPInterface[Client",
+ "BackboneInterface[Client on",
+ )
):
continue

diff --git a/meshchatx/src/backend/sticker_pack_utils.py b/meshchatx/src/backend/sticker_pack_utils.py
index 3e984ea0..31ddce74 100644
--- a/meshchatx/src/backend/sticker_pack_utils.py
+++ b/meshchatx/src/backend/sticker_pack_utils.py
@@ -124,7 +124,9 @@ def validate_pack_document(data: object) -> dict:
out_stickers.append(
{
"name": item.get("name") if isinstance(item.get("name"), str) else None,
- "emoji": item.get("emoji") if isinstance(item.get("emoji"), str) else None,
+ "emoji": item.get("emoji")
+ if isinstance(item.get("emoji"), str)
+ else None,
"image_type": item.get("image_type"),
"image_bytes_b64": b64.strip(),
},
@@ -135,7 +137,9 @@ def validate_pack_document(data: object) -> dict:
"short_name": sanitize_pack_short_name(pack_meta.get("short_name")),
"description": sanitize_pack_description(pack_meta.get("description")),
"pack_type": sanitize_pack_type(pack_meta.get("type")),
- "author": pack_meta.get("author") if isinstance(pack_meta.get("author"), str) else None,
+ "author": pack_meta.get("author")
+ if isinstance(pack_meta.get("author"), str)
+ else None,
"is_strict": bool(pack_meta.get("is_strict", True)),
},
"stickers": out_stickers,

diff --git a/meshchatx/src/backend/sticker_utils.py b/meshchatx/src/backend/sticker_utils.py
index baae94c2..4d6c2e5a 100644
--- a/meshchatx/src/backend/sticker_utils.py
+++ b/meshchatx/src/backend/sticker_utils.py
@@ -270,7 +270,9 @@ def parse_tgs(data: bytes) -> dict:
}
-def _ebml_read_vint(buf: bytes, pos: int, *, mask_marker: bool = True) -> tuple[int, int] | None:
+def _ebml_read_vint(
+ buf: bytes, pos: int, *, mask_marker: bool = True
+) -> tuple[int, int] | None:
"""Read an EBML variable-length integer at ``pos``; returns ``(value, next_pos)``."""
if pos >= len(buf):
return None
@@ -362,11 +364,15 @@ def parse_webm(data: bytes) -> dict:
if f_id == 0x83:
track_type = _ebml_read_uint(raw, fb, fe)
elif f_id == 0x86:
- track_codec = raw[fb:fe].decode("ascii", errors="replace")
+ track_codec = raw[fb:fe].decode(
+ "ascii", errors="replace"
+ )
elif f_id == 0x23E383:
track_def_dur = _ebml_read_uint(raw, fb, fe)
elif f_id == 0xE0:
- for v_id, vb, ve in _ebml_iter_elements(raw, fb, fe):
+ for v_id, vb, ve in _ebml_iter_elements(
+ raw, fb, fe
+ ):
if v_id == 0xB0:
t_w = _ebml_read_uint(raw, vb, ve)
elif v_id == 0xBA:
@@ -382,7 +388,9 @@ def parse_webm(data: bytes) -> dict:
elif seg_id == 0x1549A966:
for inf_id, ib, ie in _ebml_iter_elements(raw, sb, se):
if inf_id == 0x2AD7B1:
- timecode_scale = _ebml_read_uint(raw, ib, ie) or timecode_scale
+ timecode_scale = (
+ _ebml_read_uint(raw, ib, ie) or timecode_scale
+ )
elif inf_id == 0x4489:
d = _ebml_read_float(raw, ib, ie)
if d is not None:

diff --git a/meshchatx/src/backend/telephone_manager.py b/meshchatx/src/backend/telephone_manager.py
index b8f33f35..379ff69a 100644
--- a/meshchatx/src/backend/telephone_manager.py
+++ b/meshchatx/src/backend/telephone_manager.py
@@ -60,7 +60,9 @@ class TelephoneManager:
self.storage_dir = storage_dir
self.db = db
self.get_name_for_identity_hash = None
- self.recordings_dir = os.path.join(storage_dir, "recordings") if storage_dir else None
+ self.recordings_dir = (
+ os.path.join(storage_dir, "recordings") if storage_dir else None
+ )
if self.recordings_dir:
os.makedirs(self.recordings_dir, exist_ok=True)
@@ -443,7 +445,8 @@ class TelephoneManager:
# to ensure the UI has something to show (either active_call or initiation_status)
for _ in range(40): # Max 4 seconds of defensive waiting
if self.telephone and (
- self.telephone.active_call or self.telephone.call_status in [0, 1, 3, 6]
+ self.telephone.active_call
+ or self.telephone.call_status in [0, 1, 3, 6]
):
break
await asyncio.sleep(self._status_poll_interval_s)

diff --git a/meshchatx/src/backend/translator_handler.py b/meshchatx/src/backend/translator_handler.py
index 787beba3..4fb5e1b8 100644
--- a/meshchatx/src/backend/translator_handler.py
+++ b/meshchatx/src/backend/translator_handler.py
@@ -261,9 +261,7 @@ class TranslatorHandler:
if detected_lang:
source_lang = detected_lang
else:
- msg = (
- "Could not auto-detect language. Please select a source language manually."
- )
+ msg = "Could not auto-detect language. Please select a source language manually."
raise ValueError(msg)
else:
msg = (
@@ -363,7 +361,11 @@ class TranslatorHandler:
"source": "argos",
}
except subprocess.CalledProcessError as e:
- error_msg = e.stderr.decode() if isinstance(e.stderr, bytes) else (e.stderr or str(e))
+ error_msg = (
+ e.stderr.decode()
+ if isinstance(e.stderr, bytes)
+ else (e.stderr or str(e))
+ )
msg = f"Argos Translate CLI error: {error_msg}"
raise RuntimeError(msg) from e
except Exception as e:

diff --git a/meshchatx/src/backend/web_audio_bridge.py b/meshchatx/src/backend/web_audio_bridge.py
index c96b4fb1..1fab4e2c 100644
--- a/meshchatx/src/backend/web_audio_bridge.py
+++ b/meshchatx/src/backend/web_audio_bridge.py
@@ -48,7 +48,9 @@ class WebAudioSource(LocalSource):
def push_pcm(self, pcm_bytes: bytes):
try:
- samples = np.frombuffer(pcm_bytes, dtype=np.int16).astype(np.float32) / 32768.0
+ samples = (
+ np.frombuffer(pcm_bytes, dtype=np.int16).astype(np.float32) / 32768.0
+ )
if samples.size == 0:
return
samples = samples.reshape(-1, 1)

diff --git a/scripts/argos_translate.py b/scripts/argos_translate.py
index eb26c3d5..964705c6 100755
--- a/scripts/argos_translate.py
+++ b/scripts/argos_translate.py
@@ -93,13 +93,17 @@ def ensure_package_installed(from_code, to_code):
if pkg_to_install:
print_info(f"Downloading package: {pkg_to_install}")
argostranslate.package.install_from_path(pkg_to_install.download())
- print_success(f"Successfully installed package: {from_code} -> {to_code}")
+ print_success(
+ f"Successfully installed package: {from_code} -> {to_code}"
+ )
# Refresh installed languages
installed = argostranslate.translate.get_installed_languages()
installed_dict = {lang.code: lang for lang in installed}
else:
- print_error(f"Could not find a translation package for {from_code} -> {to_code}")
+ print_error(
+ f"Could not find a translation package for {from_code} -> {to_code}"
+ )
sys.exit(1)
except Exception as e:
print_error(f"Failed to install language package: {e}")
@@ -174,7 +178,9 @@ def translate_dict(data, translate_func, target_name=None):
translated_temp = translate_func(temp_text)
return restore_vars_from_tokens(translated_temp, vars_found)
except Exception as e:
- print_warning(f"Failed to translate '{data}': {e}. Falling back to original.")
+ print_warning(
+ f"Failed to translate '{data}': {e}. Falling back to original."
+ )
return data
else:
return data
@@ -184,7 +190,9 @@ def main():
parser = argparse.ArgumentParser(
description="Translate JSON localization files using Argos Translate."
)
- parser.add_argument("--from", dest="from_lang", help="Source language code (e.g. 'en')")
+ parser.add_argument(
+ "--from", dest="from_lang", help="Source language code (e.g. 'en')"
+ )
parser.add_argument("--to", dest="to_lang", help="Target language code (e.g. 'zh')")
parser.add_argument("--input", dest="input_file", help="Path to input JSON file")
parser.add_argument("--output", dest="output_file", help="Path to output JSON file")
@@ -232,7 +240,9 @@ def main():
# Get Translator
translate_func = get_translation_func(from_lang, to_lang)
- print_info("Starting translation. This may take a moment depending on the file size...")
+ print_info(
+ "Starting translation. This may take a moment depending on the file size..."
+ )
translated_data = translate_dict(source_data, translate_func, target_name)
# Ensure output directory exists

diff --git a/scripts/build/fetch_reticulum_manual.py b/scripts/build/fetch_reticulum_manual.py
index 6cb6e1cf..696a6261 100755
--- a/scripts/build/fetch_reticulum_manual.py
+++ b/scripts/build/fetch_reticulum_manual.py
@@ -240,7 +240,9 @@ def main(argv: list[str] | None = None) -> int:
)
if _is_truthy(os.environ.get("MESHCHATX_SKIP_DOCS_FETCH")):
- logging.info("MESHCHATX_SKIP_DOCS_FETCH is set; skipping Reticulum manual fetch.")
+ logging.info(
+ "MESHCHATX_SKIP_DOCS_FETCH is set; skipping Reticulum manual fetch."
+ )
return 0
sources: list[str] = []

diff --git a/scripts/ci/slsa-predicate.py b/scripts/ci/slsa-predicate.py
index a269d32b..f9205e5a 100644
--- a/scripts/ci/slsa-predicate.py
+++ b/scripts/ci/slsa-predicate.py
@@ -14,7 +14,9 @@ def _source_uri() -> str:
server = (
os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or ""
).rstrip("/")
- repo = os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or ""
+ repo = (
+ os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or ""
+ )
if not server or not repo:
return ""
if server.startswith(("https://", "http://")):
@@ -29,7 +31,9 @@ def _build_type() -> str:
server = (
os.environ.get("GITHUB_SERVER_URL") or os.environ.get("GITEA_SERVER_URL") or ""
).rstrip("/")
- repo = os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or ""
+ repo = (
+ os.environ.get("GITHUB_REPOSITORY") or os.environ.get("GITEA_REPOSITORY") or ""
+ )
if server and repo:
return f"{server}/{repo}/.gitea/workflows/build.yml"
return "https://slsa.dev/provenance/v1"

diff --git a/tests/backend/benchmarking_utils.py b/tests/backend/benchmarking_utils.py
index 8eb46b49..e9114ec1 100644
--- a/tests/backend/benchmarking_utils.py
+++ b/tests/backend/benchmarking_utils.py
@@ -21,9 +21,7 @@ class BenchmarkResult:
self.memory_delta_mb = memory_delta_mb
def __repr__(self):
- return (
- f"<BenchmarkResult {self.name}: {self.duration_ms:.2f}ms, {self.memory_delta_mb:.2f}MB>"
- )
+ return f"<BenchmarkResult {self.name}: {self.duration_ms:.2f}ms, {self.memory_delta_mb:.2f}MB>"
def benchmark(name=None, iterations=1):

diff --git a/tests/backend/test_audio_codec.py b/tests/backend/test_audio_codec.py
index 5a02d65d..f7fa51a1 100644
--- a/tests/backend/test_audio_codec.py
+++ b/tests/backend/test_audio_codec.py
@@ -38,7 +38,9 @@ def _build_wav_pcm16(
wf.setframerate(samplerate)
frames = bytearray()
for i in range(n_samples):
- sample = int(0.3 * 32767 * math.sin(2 * math.pi * frequency * (i / samplerate)))
+ sample = int(
+ 0.3 * 32767 * math.sin(2 * math.pi * frequency * (i / samplerate))
+ )
for _ in range(channels):
frames.extend(struct.pack("<h", sample))
wf.writeframes(bytes(frames))
@@ -192,7 +194,9 @@ def test_encode_pcm_to_ogg_opus_preserves_duration(duration_seconds):
sr = 48000
n = int(sr * duration_seconds)
t = np.arange(n, dtype=np.float32) / sr
- samples = (0.3 * np.sin(2 * math.pi * 440.0 * t)).astype(np.float32).reshape(-1, 1)
+ samples = (
+ (0.3 * np.sin(2 * math.pi * 440.0 * t)).astype(np.float32).reshape(-1, 1)
+ )
audio_codec.encode_pcm_to_ogg_opus(samples, sr, 1, out)
encoded = _ogg_opus_duration_seconds(out)
assert abs(encoded - duration_seconds) < 0.001, (
@@ -215,7 +219,9 @@ def test_encode_pcm_to_ogg_opus_audio_profile_keeps_stereo():
t = np.arange(n, dtype=np.float32) / sr
samples[:, 0] = 0.3 * np.sin(2 * math.pi * 440.0 * t)
samples[:, 1] = 0.3 * np.sin(2 * math.pi * 660.0 * t)
- audio_codec.encode_pcm_to_ogg_opus(samples, sr, 2, out, profile=Opus.PROFILE_AUDIO_MAX)
+ audio_codec.encode_pcm_to_ogg_opus(
+ samples, sr, 2, out, profile=Opus.PROFILE_AUDIO_MAX
+ )
with open(out, "rb") as f:
data = f.read()
head = data.find(b"OpusHead")

diff --git a/tests/backend/test_auto_propagation.py b/tests/backend/test_auto_propagation.py
index 22e9a341..e9538a10 100644
--- a/tests/backend/test_auto_propagation.py
+++ b/tests/backend/test_auto_propagation.py
@@ -56,7 +56,9 @@ async def test_auto_propagation_logic():
patch.object(manager, "_wait_for_path", return_value=True),
patch.object(manager, "_probe_propagation_sync", return_value=True),
):
- mock_hops.side_effect = lambda dh: 1 if dh == bytes.fromhex(_VALID_HASH_A) else 3
+ mock_hops.side_effect = lambda dh: (
+ 1 if dh == bytes.fromhex(_VALID_HASH_A) else 3
+ )
await manager.check_and_update_propagation_node()
@@ -68,7 +70,9 @@ async def test_auto_propagation_logic():
_VALID_HASH_A,
)
- config.lxmf_preferred_propagation_node_destination_hash.get.return_value = _VALID_HASH_B
+ config.lxmf_preferred_propagation_node_destination_hash.get.return_value = (
+ _VALID_HASH_B
+ )
app.set_active_propagation_node.reset_mock()
with (
@@ -77,7 +81,9 @@ async def test_auto_propagation_logic():
patch.object(manager, "_wait_for_path", return_value=True),
patch.object(manager, "_probe_propagation_sync", side_effect=[False, True]),
):
- mock_hops.side_effect = lambda dh: 1 if dh == bytes.fromhex(_VALID_HASH_A) else 3
+ mock_hops.side_effect = lambda dh: (
+ 1 if dh == bytes.fromhex(_VALID_HASH_A) else 3
+ )
await manager.check_and_update_propagation_node()
@@ -86,7 +92,9 @@ async def test_auto_propagation_logic():
context=context,
)
- config.lxmf_preferred_propagation_node_destination_hash.get.return_value = _VALID_HASH_C
+ config.lxmf_preferred_propagation_node_destination_hash.get.return_value = (
+ _VALID_HASH_C
+ )
announce3 = {
"destination_hash": _VALID_HASH_C,
"app_data": _APP_DATA_ENABLED,
@@ -100,7 +108,9 @@ async def test_auto_propagation_logic():
patch.object(manager, "_wait_for_path", return_value=True),
patch.object(manager, "_probe_propagation_sync", return_value=True),
):
- mock_hops.side_effect = lambda dh: 1 if dh == bytes.fromhex(_VALID_HASH_A) else 2
+ mock_hops.side_effect = lambda dh: (
+ 1 if dh == bytes.fromhex(_VALID_HASH_A) else 2
+ )
await manager.check_and_update_propagation_node()

diff --git a/tests/backend/test_auto_propagation_api.py b/tests/backend/test_auto_propagation_api.py
index 692cbe8a..9b5d11b8 100644
--- a/tests/backend/test_auto_propagation_api.py
+++ b/tests/backend/test_auto_propagation_api.py
@@ -103,7 +103,9 @@ async def test_auto_propagation_api(mock_rns_minimal, temp_dir):
response = await patch_handler(mock_request)
data = json.loads(response.body)
assert data["config"]["lxmf_preferred_propagation_node_auto_select"] is False
- assert app_instance.config.lxmf_preferred_propagation_node_auto_select.get() is False
+ assert (
+ app_instance.config.lxmf_preferred_propagation_node_auto_select.get() is False
+ )
# Update transfer/sync limits and validate clamping/application
mock_request = MagicMock()
@@ -131,5 +133,7 @@ async def test_auto_propagation_api(mock_rns_minimal, temp_dir):
response = await patch_handler(mock_request)
data = json.loads(response.body)
assert data["config"]["lxmf_delivery_transfer_limit_in_bytes"] == 1_000_000_000
- assert app_instance.config.lxmf_delivery_transfer_limit_in_bytes.get() == 1_000_000_000
+ assert (
+ app_instance.config.lxmf_delivery_transfer_limit_in_bytes.get() == 1_000_000_000
+ )
assert app_instance.message_router.delivery_per_transfer_limit == 1_000_000

diff --git a/tests/backend/test_bot_handler_extended.py b/tests/backend/test_bot_handler_extended.py
index 09fafc56..de27e253 100644
--- a/tests/backend/test_bot_handler_extended.py
+++ b/tests/backend/test_bot_handler_extended.py
@@ -111,7 +111,9 @@ def test_get_status_reads_sidecar_lxmf_address(temp_identity_dir):
storage = os.path.join(handler.bots_dir, sid)
os.makedirs(storage, exist_ok=True)
hx = "a" * 32
- with open(os.path.join(storage, "meshchatx_lxmf_address.txt"), "w", encoding="utf-8") as f:
+ with open(
+ os.path.join(storage, "meshchatx_lxmf_address.txt"), "w", encoding="utf-8"
+ ) as f:
f.write(hx)
handler.bots_state = [{"id": sid, "template_id": "echo", "storage_dir": storage}]
status = handler.get_status()
@@ -176,7 +178,9 @@ def test_request_announce_writes_trigger(mock_alive, temp_identity_dir):
sid = "b1"
storage = os.path.join(handler.bots_dir, sid)
os.makedirs(storage, exist_ok=True)
- handler.bots_state = [{"id": sid, "template_id": "echo", "storage_dir": storage, "pid": 99999}]
+ handler.bots_state = [
+ {"id": sid, "template_id": "echo", "storage_dir": storage, "pid": 99999}
+ ]
handler.request_announce(sid)
req = os.path.join(storage, "meshchatx_request_announce")
assert os.path.isfile(req)
@@ -189,6 +193,8 @@ def test_request_announce_not_running(temp_identity_dir):
sid = "b1"
storage = os.path.join(handler.bots_dir, sid)
os.makedirs(storage, exist_ok=True)
- handler.bots_state = [{"id": sid, "template_id": "echo", "storage_dir": storage, "pid": None}]
+ handler.bots_state = [
+ {"id": sid, "template_id": "echo", "storage_dir": storage, "pid": None}
+ ]
with pytest.raises(RuntimeError, match="not running"):
handler.request_announce(sid)

diff --git a/tests/backend/test_concurrency_stress.py b/tests/backend/test_concurrency_stress.py
index f0cf0bc4..71e2cd3c 100644
--- a/tests/backend/test_concurrency_stress.py
+++ b/tests/backend/test_concurrency_stress.py
@@ -91,8 +91,12 @@ class TestConcurrencyStress(unittest.TestCase):
def test_database_concurrency(self):
"""Launches multiple reader and writer threads to check for lock contention."""
- writers = [threading.Thread(target=self.db_writer_worker, args=(i,)) for i in range(5)]
- readers = [threading.Thread(target=self.db_reader_worker, args=(i,)) for i in range(5)]
+ writers = [
+ threading.Thread(target=self.db_writer_worker, args=(i,)) for i in range(5)
+ ]
+ readers = [
+ threading.Thread(target=self.db_reader_worker, args=(i,)) for i in range(5)
+ ]
for t in writers + readers:
t.start()

diff --git a/tests/backend/test_contacts_display_name_semantics.py b/tests/backend/test_contacts_display_name_semantics.py
index 9f38c861..ccdb74e3 100644
--- a/tests/backend/test_contacts_display_name_semantics.py
+++ b/tests/backend/test_contacts_display_name_semantics.py
@@ -176,7 +176,9 @@ class TestCustomDisplayNameLifecycle:
def test_unicode_display_name(self, announce_dao):
announce_dao.upsert_custom_display_name("dest1", "\u5c71\u7530\u592a\u90ce")
- assert announce_dao.get_custom_display_name("dest1") == "\u5c71\u7530\u592a\u90ce"
+ assert (
+ announce_dao.get_custom_display_name("dest1") == "\u5c71\u7530\u592a\u90ce"
+ )
def test_very_long_display_name(self, announce_dao):
long_name = "A" * 10000

diff --git a/tests/backend/test_contacts_export_import.py b/tests/backend/test_contacts_export_import.py
index d9e74c00..fd8fb7e6 100644
--- a/tests/backend/test_contacts_export_import.py
+++ b/tests/backend/test_contacts_export_import.py
@@ -48,7 +48,10 @@ async def test_contacts_export_empty(mock_rns_minimal, temp_dir):
)
handler = None
for route in app.get_routes():
- if route.path == "/api/v1/telephone/contacts/export" and route.method == "GET":
+ if (
+ route.path == "/api/v1/telephone/contacts/export"
+ and route.method == "GET"
+ ):
handler = route.handler
break
assert handler is not None
@@ -73,7 +76,10 @@ async def test_contacts_export_with_data(mock_rns_minimal, temp_dir):
handler = None
for route in app.get_routes():
- if route.path == "/api/v1/telephone/contacts/export" and route.method == "GET":
+ if (
+ route.path == "/api/v1/telephone/contacts/export"
+ and route.method == "GET"
+ ):
handler = route.handler
break
assert handler is not None
@@ -101,7 +107,10 @@ async def test_contacts_import_valid(mock_rns_minimal, temp_dir):
)
handler = None
for route in app.get_routes():
- if route.path == "/api/v1/telephone/contacts/import" and route.method == "POST":
+ if (
+ route.path == "/api/v1/telephone/contacts/import"
+ and route.method == "POST"
+ ):
handler = route.handler
break
assert handler is not None
@@ -138,7 +147,10 @@ async def test_contacts_import_skips_invalid(mock_rns_minimal, temp_dir):
)
handler = None
for route in app.get_routes():
- if route.path == "/api/v1/telephone/contacts/import" and route.method == "POST":
+ if (
+ route.path == "/api/v1/telephone/contacts/import"
+ and route.method == "POST"
+ ):
handler = route.handler
break
assert handler is not None
@@ -169,7 +181,10 @@ async def test_contacts_import_rejects_non_array(mock_rns_minimal, temp_dir):
)
handler = None
for route in app.get_routes():
- if route.path == "/api/v1/telephone/contacts/import" and route.method == "POST":
+ if (
+ route.path == "/api/v1/telephone/contacts/import"
+ and route.method == "POST"
+ ):
handler = route.handler
break
assert handler is not None

diff --git a/tests/backend/test_csp_logic.py b/tests/backend/test_csp_logic.py
index 587c51f3..f660eda0 100644
--- a/tests/backend/test_csp_logic.py
+++ b/tests/backend/test_csp_logic.py
@@ -113,6 +113,7 @@ async def test_config_update_csp(mock_rns_minimal, tmp_path):
assert response.status == 200
assert (
- app_instance.config.csp_extra_connect_src.get() == "https://api1.com, https://api2.com"
+ app_instance.config.csp_extra_connect_src.get()
+ == "https://api1.com, https://api2.com"
)
assert app_instance.config.csp_extra_img_src.get() == "https://img.com"

diff --git a/tests/backend/test_dao_fuzzing.py b/tests/backend/test_dao_fuzzing.py
index 909d4109..ae4c437a 100644
--- a/tests/backend/test_dao_fuzzing.py
+++ b/tests/backend/test_dao_fuzzing.py
@@ -662,7 +662,9 @@ class TestSafeHrefFuzzing:
url = f"{scheme}:something"
result = _safe_href(url)
lower = url.strip().lower()
- if any(lower.startswith(p) for p in ("https://", "http://", "/", "#", "mailto:")):
+ if any(
+ lower.startswith(p) for p in ("https://", "http://", "/", "#", "mailto:")
+ ):
assert result == url
else:
assert result == "#"

diff --git a/tests/backend/test_database_snapshots.py b/tests/backend/test_database_snapshots.py
index cdc285b2..8767e8f5 100644
--- a/tests/backend/test_database_snapshots.py
+++ b/tests/backend/test_database_snapshots.py
@@ -139,7 +139,9 @@ def test_backup_suspicious_when_messages_gone_skips_cleanup_and_baseline(temp_di
assert "baseline" in result2
assert result2["baseline"]["message_count"] == 1
assert result2["current_stats"]["message_count"] == 0
- zip_count_after_suspicious = sum(1 for f in os.listdir(backup_dir) if f.endswith(".zip"))
+ zip_count_after_suspicious = sum(
+ 1 for f in os.listdir(backup_dir) if f.endswith(".zip")
+ )
assert zip_count_after_suspicious == 2
assert any("SUSPICIOUS" in f for f in os.listdir(backup_dir) if f.endswith(".zip"))
with open(os.path.join(backup_dir, "backup-baseline.json")) as f:
@@ -302,8 +304,13 @@ def test_is_backup_suspicious_does_not_mistrigger_empty_baseline():
db = Database(":memory:")
db.initialize()
- assert db._is_backup_suspicious({"message_count": 0, "total_bytes": 0}, None) is False
- assert db._is_backup_suspicious({"message_count": 10, "total_bytes": 1000}, None) is False
+ assert (
+ db._is_backup_suspicious({"message_count": 0, "total_bytes": 0}, None) is False
+ )
+ assert (
+ db._is_backup_suspicious({"message_count": 10, "total_bytes": 1000}, None)
+ is False
+ )
def test_is_backup_suspicious_does_not_mistrigger_legitimate_empty():
@@ -312,7 +319,10 @@ def test_is_backup_suspicious_does_not_mistrigger_legitimate_empty():
db = Database(":memory:")
db.initialize()
baseline = {"message_count": 0, "total_bytes": 5000}
- assert db._is_backup_suspicious({"message_count": 0, "total_bytes": 5000}, baseline) is False
+ assert (
+ db._is_backup_suspicious({"message_count": 0, "total_bytes": 5000}, baseline)
+ is False
+ )
def test_is_backup_suspicious_does_not_mistrigger_small_db():
@@ -321,4 +331,7 @@ def test_is_backup_suspicious_does_not_mistrigger_small_db():
db = Database(":memory:")
db.initialize()
baseline = {"message_count": 5, "total_bytes": 50_000}
- assert db._is_backup_suspicious({"message_count": 5, "total_bytes": 55_000}, baseline) is False
+ assert (
+ db._is_backup_suspicious({"message_count": 5, "total_bytes": 55_000}, baseline)
+ is False
+ )

diff --git a/tests/backend/test_docs_manager.py b/tests/backend/test_docs_manager.py
index 77de751f..59472471 100644
--- a/tests/backend/test_docs_manager.py
+++ b/tests/backend/test_docs_manager.py
@@ -123,7 +123,10 @@ def test_docs_manager_readonly_public_dir_handling(tmp_path):
with patch("os.makedirs", side_effect=OSError("Read-only file system")):
dm = DocsManager(config, str(public_dir))
assert dm.last_error is not None
- assert "Read-only file system" in dm.last_error or "Permission denied" in dm.last_error
+ assert (
+ "Read-only file system" in dm.last_error
+ or "Permission denied" in dm.last_error
+ )
os.chmod(public_dir, 0o755) # noqa: S103

diff --git a/tests/backend/test_fuzzing.py b/tests/backend/test_fuzzing.py
index 72df3a31..4b3c77ca 100644
--- a/tests/backend/test_fuzzing.py
+++ b/tests/backend/test_fuzzing.py
@@ -283,10 +283,10 @@ def mock_app(temp_dir):
app.config.auto_send_failed_messages_to_propagation_node.get.return_value = True
app.config.show_suggested_community_interfaces.get.return_value = True
app.config.lxmf_local_propagation_node_enabled.get.return_value = False
- app.config.lxmf_preferred_propagation_node_destination_hash.get.return_value = None
- app.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get.return_value = (
- 3600
+ app.config.lxmf_preferred_propagation_node_destination_hash.get.return_value = (
+ None
)
+ app.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get.return_value = 3600
app.config.lxmf_preferred_propagation_node_last_synced_at.get.return_value = 0
app.config.lxmf_user_icon_name.get.return_value = "user"
app.config.lxmf_user_icon_foreground_colour.get.return_value = "#ffffff"
@@ -297,10 +297,16 @@ def mock_app(temp_dir):
app.config.lxmf_auto_sync_propagation_nodes_min_hops.get.return_value = 1
app.config.lxmf_auto_sync_propagation_nodes_max_hops.get.return_value = 5
app.config.lxmf_auto_sync_propagation_nodes_max_count.get.return_value = 10
- app.config.lxmf_auto_sync_propagation_nodes_max_age_seconds.get.return_value = 86400
- app.config.lxmf_auto_sync_propagation_nodes_max_size_bytes.get.return_value = 1000000
+ app.config.lxmf_auto_sync_propagation_nodes_max_age_seconds.get.return_value = (
+ 86400
+ )
+ app.config.lxmf_auto_sync_propagation_nodes_max_size_bytes.get.return_value = (
+ 1000000
+ )
app.config.lxmf_auto_sync_propagation_nodes_max_total_size_bytes.get.return_value = 10000000
- app.config.lxmf_auto_sync_propagation_nodes_max_total_count.get.return_value = 100
+ app.config.lxmf_auto_sync_propagation_nodes_max_total_count.get.return_value = (
+ 100
+ )
app.config.lxmf_auto_sync_propagation_nodes_max_total_age_seconds.get.return_value = 864000
app.config.lxmf_auto_sync_propagation_nodes_max_total_size_bytes_per_node.get.return_value = 1000000
app.config.lxmf_auto_sync_propagation_nodes_max_total_count_per_node.get.return_value = 100

diff --git a/tests/backend/test_identity_switch.py b/tests/backend/test_identity_switch.py
index 799e22e7..77864f0f 100644
--- a/tests/backend/test_identity_switch.py
+++ b/tests/backend/test_identity_switch.py
@@ -59,7 +59,9 @@ def mock_rns():
# Apply patches
mocks = {}
for p in patches:
- attr_name = p.attribute if hasattr(p, "attribute") else p.target.split(".")[-1]
+ attr_name = (
+ p.attribute if hasattr(p, "attribute") else p.target.split(".")[-1]
+ )
mocks[attr_name] = stack.enter_context(p)
# Mock class methods on MockIdentityClass

diff --git a/tests/backend/test_integrity.py b/tests/backend/test_integrity.py
index 9e987679..07b69786 100644
--- a/tests/backend/test_integrity.py
+++ b/tests/backend/test_integrity.py
@@ -87,7 +87,8 @@ class TestIntegrityManager(unittest.TestCase):
self.assertFalse(is_ok)
self.assertTrue(
any(
- "Critical security component" in i or "File signature mismatch" in i for i in issues
+ "Critical security component" in i or "File signature mismatch" in i
+ for i in issues
),
)

diff --git a/tests/backend/test_interface_discovery.py b/tests/backend/test_interface_discovery.py
index a4e34c3d..4a7bb699 100644
--- a/tests/backend/test_interface_discovery.py
+++ b/tests/backend/test_interface_discovery.py
@@ -100,7 +100,9 @@ async def test_reticulum_discovery_get_and_patch(temp_dir):
assert get_data["discovery"]["discover_interfaces"] == "true"
assert get_data["discovery"]["interface_discovery_sources"] == "abc,def"
assert get_data["discovery"]["interface_discovery_whitelist"] == "tcp-*,10.0.*"
- assert get_data["discovery"]["interface_discovery_blacklist"] == "tcp-bad,*:9999"
+ assert (
+ get_data["discovery"]["interface_discovery_blacklist"] == "tcp-bad,*:9999"
+ )
assert get_data["discovery"]["required_discovery_value"] == "16"
assert get_data["discovery"]["autoconnect_discovered_interfaces"] == "2"
assert get_data["discovery"]["network_identity"] == "/tmp/net_id"
@@ -125,7 +127,10 @@ async def test_reticulum_discovery_get_and_patch(temp_dir):
patch_data = json.loads(patch_response.body)
assert patch_data["discovery"]["discover_interfaces"] is False
assert patch_data["discovery"]["interface_discovery_sources"] is None
- assert patch_data["discovery"]["interface_discovery_whitelist"] == "peer-*,172.16.*"
+ assert (
+ patch_data["discovery"]["interface_discovery_whitelist"]
+ == "peer-*,172.16.*"
+ )
assert patch_data["discovery"]["interface_discovery_blacklist"] is None
assert patch_data["discovery"]["required_discovery_value"] == 18
assert patch_data["discovery"]["autoconnect_discovered_interfaces"] == 5
@@ -258,9 +263,15 @@ async def test_discovery_patch_sanitizes_whitelist_blacklist_values(temp_dir):
data = json.loads(response.body)
assert data["discovery"]["interface_discovery_whitelist"] == "peer-1,host:4242"
- assert data["discovery"]["interface_discovery_blacklist"] == "bad-node,evilentry"
- assert config["reticulum"]["interface_discovery_whitelist"] == "peer-1,host:4242"
- assert config["reticulum"]["interface_discovery_blacklist"] == "bad-node,evilentry"
+ assert (
+ data["discovery"]["interface_discovery_blacklist"] == "bad-node,evilentry"
+ )
+ assert (
+ config["reticulum"]["interface_discovery_whitelist"] == "peer-1,host:4242"
+ )
+ assert (
+ config["reticulum"]["interface_discovery_blacklist"] == "bad-node,evilentry"
+ )
assert config.write_called

diff --git a/tests/backend/test_interface_discovery_ifac.py b/tests/backend/test_interface_discovery_ifac.py
index 56b8f645..27b8fc7b 100644
--- a/tests/backend/test_interface_discovery_ifac.py
+++ b/tests/backend/test_interface_discovery_ifac.py
@@ -61,7 +61,9 @@ async def find_route_handler(app_instance, path, method):
def test_normalize_handles_non_list_input():
- assert ReticulumMeshChat.normalize_discovered_ifac_fields({"foo": "bar"}) == {"foo": "bar"}
+ assert ReticulumMeshChat.normalize_discovered_ifac_fields({"foo": "bar"}) == {
+ "foo": "bar"
+ }
assert ReticulumMeshChat.normalize_discovered_ifac_fields(None) is None

diff --git a/tests/backend/test_licenses_collector.py b/tests/backend/test_licenses_collector.py
index 235a66c4..05e5ecd2 100644
--- a/tests/backend/test_licenses_collector.py
+++ b/tests/backend/test_licenses_collector.py
@@ -102,8 +102,12 @@ def test_build_licenses_payload_composes_counts_and_meta():
def test_render_third_party_notices_contains_sections_and_rows():
payload = {
- "backend": [{"name": "rns", "version": "1.0", "author": "Author A", "license": "MIT"}],
- "frontend": [{"name": "vue", "version": "3.0", "author": "Author B", "license": "MIT"}],
+ "backend": [
+ {"name": "rns", "version": "1.0", "author": "Author A", "license": "MIT"}
+ ],
+ "frontend": [
+ {"name": "vue", "version": "3.0", "author": "Author B", "license": "MIT"}
+ ],
"meta": {"generated_at": "2026-01-01T00:00:00Z", "frontend_source": "pnpm"},
}
rendered = render_third_party_notices(payload)
@@ -131,7 +135,9 @@ def test_write_embedded_license_artifacts_writes_files(tmp_path):
assert frontend_path.exists()
assert notices_path.exists()
assert '"name": "vue"' in frontend_path.read_text(encoding="utf-8")
- assert "Reticulum MeshChatX - Third-party notices" in notices_path.read_text(encoding="utf-8")
+ assert "Reticulum MeshChatX - Third-party notices" in notices_path.read_text(
+ encoding="utf-8"
+ )
def test_write_embedded_license_artifacts_preserves_existing_frontend_when_empty(

diff --git a/tests/backend/test_lxmf_attachments.py b/tests/backend/test_lxmf_attachments.py
index 0a6a0ce7..38518522 100644
--- a/tests/backend/test_lxmf_attachments.py
+++ b/tests/backend/test_lxmf_attachments.py
@@ -18,7 +18,9 @@ def test_message_fields_have_attachments():
assert message_fields_have_attachments(json.dumps({"audio": "base64data"})) is True
# File attachments - empty list
- assert message_fields_have_attachments(json.dumps({"file_attachments": []})) is False
+ assert (
+ message_fields_have_attachments(json.dumps({"file_attachments": []})) is False
+ )
# File attachments - with files
assert (

diff --git a/tests/backend/test_lxmf_icons.py b/tests/backend/test_lxmf_icons.py
index 416b49f3..13c386f1 100644
--- a/tests/backend/test_lxmf_icons.py
+++ b/tests/backend/test_lxmf_icons.py
@@ -61,7 +61,9 @@ def mock_rns():
# Apply patches
mocks = {}
for p in patches:
- attr_name = p.attribute if hasattr(p, "attribute") else p.target.split(".")[-1]
+ attr_name = (
+ p.attribute if hasattr(p, "attribute") else p.target.split(".")[-1]
+ )
mocks[attr_name] = stack.enter_context(p)
# Access specifically the ones we need to configure
@@ -70,11 +72,13 @@ def mock_rns():
# Setup mock config
mock_config.return_value.display_name.get.return_value = "Test User"
mock_config.return_value.lxmf_user_icon_name.get.return_value = "user"
- mock_config.return_value.lxmf_user_icon_foreground_colour.get.return_value = "#ffffff"
- mock_config.return_value.lxmf_user_icon_background_colour.get.return_value = "#000000"
- mock_config.return_value.auto_send_failed_messages_to_propagation_node.get.return_value = (
- False
+ mock_config.return_value.lxmf_user_icon_foreground_colour.get.return_value = (
+ "#ffffff"
)
+ mock_config.return_value.lxmf_user_icon_background_colour.get.return_value = (
+ "#000000"
+ )
+ mock_config.return_value.auto_send_failed_messages_to_propagation_node.get.return_value = False
# Mock class methods on MockIdentityClass
mock_id_instance = MockIdentityClass()

diff --git a/tests/backend/test_lxmf_propagation_full.py b/tests/backend/test_lxmf_propagation_full.py
index 5db70fbb..7db609a2 100644
--- a/tests/backend/test_lxmf_propagation_full.py
+++ b/tests/backend/test_lxmf_propagation_full.py
@@ -104,7 +104,10 @@ async def test_lxmf_propagation_config(mock_app):
mock_app.current_context.message_router.set_outbound_propagation_node.assert_called_with(
node_hash_bytes,
)
- assert mock_app.config.lxmf_preferred_propagation_node_destination_hash.get() == node_hash_hex
+ assert (
+ mock_app.config.lxmf_preferred_propagation_node_destination_hash.get()
+ == node_hash_hex
+ )
@pytest.mark.asyncio
@@ -125,7 +128,9 @@ async def test_lxmf_sync_flow(mock_app):
mock_router.propagation_transfer_progress = 0.75
status_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/status"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/status"
)
response = await status_handler(None)
data = json.loads(response.body)
@@ -139,7 +144,9 @@ async def test_lxmf_sync_requests_path_before_sync(mock_app):
outbound = b"somehash"
mock_router.get_outbound_propagation_node.return_value = outbound
sync_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/sync"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/sync"
)
with patch("meshchatx.meshchat.RNS.Transport.has_path", return_value=False):
@@ -158,7 +165,9 @@ async def test_lxmf_sync_completes_immediately_for_local_preferred_node(mock_app
mock_router.propagation_destination = SimpleNamespace(hash=local_hash)
mock_router.get_outbound_propagation_node.return_value = local_hash
sync_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/sync"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/sync"
)
await sync_handler(None)
@@ -203,14 +212,19 @@ async def test_auto_sync_interval_config(mock_app):
await mock_app.update_config(
{"lxmf_preferred_propagation_node_auto_sync_interval_seconds": 3600},
)
- assert mock_app.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get() == 3600
+ assert (
+ mock_app.config.lxmf_preferred_propagation_node_auto_sync_interval_seconds.get()
+ == 3600
+ )
@pytest.mark.asyncio
async def test_propagation_node_status_mapping(mock_app):
mock_router = mock_app.current_context.message_router
status_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/status"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/status"
)
states_to_test = [
@@ -257,7 +271,9 @@ async def test_local_propagation_node_stop_and_restart_routes(mock_app):
}
stop_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/stop"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/stop"
)
restart_handler = next(
r.handler
@@ -302,13 +318,13 @@ async def test_user_provided_node_hash(mock_app):
)
# Trigger a sync request
- mock_app.current_context.message_router.get_outbound_propagation_node.return_value = (
- bytes.fromhex(
- node_hash_hex,
- )
+ mock_app.current_context.message_router.get_outbound_propagation_node.return_value = bytes.fromhex(
+ node_hash_hex,
)
sync_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/sync"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/sync"
)
await sync_handler(None)

diff --git a/tests/backend/test_lxmf_propagation_sync_integration.py b/tests/backend/test_lxmf_propagation_sync_integration.py
index cc5065d3..f702e4f9 100644
--- a/tests/backend/test_lxmf_propagation_sync_integration.py
+++ b/tests/backend/test_lxmf_propagation_sync_integration.py
@@ -104,7 +104,9 @@ def integration_app(temp_dir):
def _route_handler(app, path, method="GET"):
- return next(r.handler for r in app.get_routes() if r.path == path and r.method == method)
+ return next(
+ r.handler for r in app.get_routes() if r.path == path and r.method == method
+ )
@pytest.mark.asyncio
@@ -133,18 +135,24 @@ async def test_remote_propagation_sync_transitions_path_requested_to_complete(
with (
patch("meshchatx.meshchat.RNS.Transport.has_path", side_effect=has_path),
- patch("meshchatx.meshchat.RNS.Transport.request_path", side_effect=request_path),
+ patch(
+ "meshchatx.meshchat.RNS.Transport.request_path", side_effect=request_path
+ ),
):
first_sync = await sync_handler(None)
assert first_sync.status == 200
- first_status = json.loads((await status_handler(None)).body)["propagation_node_status"]
+ first_status = json.loads((await status_handler(None)).body)[
+ "propagation_node_status"
+ ]
assert first_status["state"] == "path_requested"
second_sync = await sync_handler(None)
assert second_sync.status == 200
- second_status = json.loads((await status_handler(None)).body)["propagation_node_status"]
+ second_status = json.loads((await status_handler(None)).body)[
+ "propagation_node_status"
+ ]
assert second_status["state"] == "complete"
assert second_status["progress"] == 100.0
assert fake_router.request_messages_calls >= 2
@@ -169,7 +177,9 @@ async def test_local_preferred_propagation_sync_completes_without_remote_lookup(
response = await sync_handler(None)
assert response.status == 200
- status_data = json.loads((await status_handler(None)).body)["propagation_node_status"]
+ status_data = json.loads((await status_handler(None)).body)[
+ "propagation_node_status"
+ ]
assert status_data["state"] == "complete"
assert status_data["progress"] == 100.0
assert fake_router.request_messages_calls == 0

diff --git a/tests/backend/test_lxmf_sync.py b/tests/backend/test_lxmf_sync.py
index 743a92e9..32166566 100644
--- a/tests/backend/test_lxmf_sync.py
+++ b/tests/backend/test_lxmf_sync.py
@@ -78,7 +78,10 @@ async def test_lxmf_sync_endpoints(mock_app):
# 1. Test status endpoint initially idle
handler = None
for route in mock_app.get_routes():
- if route.path == "/api/v1/lxmf/propagation-node/status" and route.method == "GET":
+ if (
+ route.path == "/api/v1/lxmf/propagation-node/status"
+ and route.method == "GET"
+ ):
handler = route.handler
break
@@ -104,7 +107,9 @@ async def test_lxmf_sync_endpoints(mock_app):
mock_app.current_context.message_router.request_messages_from_propagation_node.assert_called_once()
# 3. Test status change to complete
- mock_app.current_context.message_router.propagation_transfer_state = LXMF.LXMRouter.PR_COMPLETE
+ mock_app.current_context.message_router.propagation_transfer_state = (
+ LXMF.LXMRouter.PR_COMPLETE
+ )
response = await handler(None)
data = json.loads(response.body)
assert data["propagation_node_status"]["state"] == "complete"
@@ -135,9 +140,7 @@ async def test_specific_node_hash_validation(mock_app):
break
# Ensure it's considered configured
- mock_app.current_context.message_router.get_outbound_propagation_node.return_value = (
- expected_bytes
- )
+ mock_app.current_context.message_router.get_outbound_propagation_node.return_value = expected_bytes
await sync_handler(None)
mock_app.current_context.message_router.request_messages_from_propagation_node.assert_called_once()
@@ -146,10 +149,14 @@ async def test_specific_node_hash_validation(mock_app):
@pytest.mark.asyncio
async def test_status_includes_sync_storage_and_confirmation_metrics(mock_app):
status_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/status"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/status"
)
sync_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/sync"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/sync"
)
mock_app.current_context.message_router.get_outbound_propagation_node.return_value = b"somehash"
@@ -180,7 +187,9 @@ async def test_status_includes_sync_storage_and_confirmation_metrics(mock_app):
@pytest.mark.asyncio
async def test_status_metrics_default_to_zero_before_any_sync(mock_app):
status_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/status"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/status"
)
response = await status_handler(None)
data = json.loads(response.body)["propagation_node_status"]
@@ -194,10 +203,14 @@ async def test_status_metrics_default_to_zero_before_any_sync(mock_app):
@pytest.mark.asyncio
async def test_status_hidden_metric_is_clamped_to_zero(mock_app):
status_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/status"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/status"
)
sync_handler = next(
- r.handler for r in mock_app.get_routes() if r.path == "/api/v1/lxmf/propagation-node/sync"
+ r.handler
+ for r in mock_app.get_routes()
+ if r.path == "/api/v1/lxmf/propagation-node/sync"
)
mock_app.current_context.message_router.get_outbound_propagation_node.return_value = b"somehash"

diff --git a/tests/backend/test_lxmf_utils_extended.py b/tests/backend/test_lxmf_utils_extended.py
index fb4b1adf..ea2c1683 100644
--- a/tests/backend/test_lxmf_utils_extended.py
+++ b/tests/backend/test_lxmf_utils_extended.py
@@ -76,9 +76,15 @@ def test_convert_lxmf_message_to_dict_with_attachments():
== base64.b64encode(b"content1").decode()
)
assert result["fields"]["image"]["image_type"] == "png"
- assert result["fields"]["image"]["image_bytes"] == base64.b64encode(b"image_data").decode()
+ assert (
+ result["fields"]["image"]["image_bytes"]
+ == base64.b64encode(b"image_data").decode()
+ )
assert result["fields"]["audio"]["audio_mode"] == "voice"
- assert result["fields"]["audio"]["audio_bytes"] == base64.b64encode(b"audio_data").decode()
+ assert (
+ result["fields"]["audio"]["audio_bytes"]
+ == base64.b64encode(b"audio_data").decode()
+ )
def test_convert_lxmf_state_to_string():

diff --git a/tests/backend/test_markdown_renderer.py b/tests/backend/test_markdown_renderer.py
index c608aae0..8014d279 100644
--- a/tests/backend/test_markdown_renderer.py
+++ b/tests/backend/test_markdown_renderer.py
@@ -26,7 +26,8 @@ class TestMarkdownRenderer(unittest.TestCase):
self.assertIn("<code", rendered)
self.assertIn("language-python", rendered)
self.assertTrue(
- "print(&#x27;hello&#x27;)" in rendered or "print(&#039;hello&#039;)" in rendered,
+ "print(&#x27;hello&#x27;)" in rendered
+ or "print(&#039;hello&#039;)" in rendered,
)
def test_lists(self):

diff --git a/tests/backend/test_media_fuzzing.py b/tests/backend/test_media_fuzzing.py
index bb24c416..93fa9ca8 100644
--- a/tests/backend/test_media_fuzzing.py
+++ b/tests/backend/test_media_fuzzing.py
@@ -62,7 +62,9 @@ def test_parse_tgs_gzip_json_fuzz(payload):
merged.setdefault("op", 60.0)
merged.setdefault("w", 100)
merged.setdefault("h", 100)
- raw = gzip.compress(json.dumps(merged, default=str).encode("utf-8", errors="surrogateescape"))
+ raw = gzip.compress(
+ json.dumps(merged, default=str).encode("utf-8", errors="surrogateescape")
+ )
if len(raw) > sticker_utils.MAX_ANIMATED_BYTES:
raw = raw[: sticker_utils.MAX_ANIMATED_BYTES]
try:
@@ -116,7 +118,9 @@ def test_extract_metadata_fuzz_never_raises(image_type, raw):
typ=st.one_of(
st.none(),
st.text(max_size=48),
- st.sampled_from(["png", "jpeg", "jpg", "webp", "gif", "bmp", "tgs", "webm", "svg", ""]),
+ st.sampled_from(
+ ["png", "jpeg", "jpg", "webp", "gif", "bmp", "tgs", "webm", "svg", ""]
+ ),
),
strict=st.booleans(),
)
@@ -161,7 +165,9 @@ def test_mime_for_image_type_fuzz_never_raises(t):
description=st.one_of(st.none(), st.text(max_size=400)),
pack_type=st.one_of(st.none(), st.text(max_size=40)),
)
-def test_sticker_pack_sanitizers_fuzz_never_raises(title, short_name, description, pack_type):
+def test_sticker_pack_sanitizers_fuzz_never_raises(
+ title, short_name, description, pack_type
+):
sticker_pack_utils.sanitize_pack_title(title)
sticker_pack_utils.sanitize_pack_short_name(short_name)
sticker_pack_utils.sanitize_pack_description(description)

diff --git a/tests/backend/test_meshchat_coverage.py b/tests/backend/test_meshchat_coverage.py
index c747537f..31bc97df 100644
--- a/tests/backend/test_meshchat_coverage.py
+++ b/tests/backend/test_meshchat_coverage.py
@@ -452,7 +452,9 @@ def _build_wav_pcm16(samplerate=48000, duration_seconds=0.5, frequency=440.0):
wf.setframerate(samplerate)
frames = bytearray()
for i in range(n_samples):
- sample = int(0.3 * 32767 * math.sin(2 * math.pi * frequency * (i / samplerate)))
+ sample = int(
+ 0.3 * 32767 * math.sin(2 * math.pi * frequency * (i / samplerate))
+ )
frames.extend(struct.pack("<h", sample))
wf.writeframes(bytes(frames))
return buf.getvalue()

diff --git a/tests/backend/test_package_version_resolution.py b/tests/backend/test_package_version_resolution.py
index dcd56d88..13c0b848 100644
--- a/tests/backend/test_package_version_resolution.py
+++ b/tests/backend/test_package_version_resolution.py
@@ -84,7 +84,9 @@ def test_app_info_dependency_keys_resolve_in_dev_env(package: str):
assert v != "unknown", f"{package} must resolve when installed"
-@pytest.mark.skipif(sys.version_info < (3, 13), reason="audioop-lts only on Python 3.13+")
+@pytest.mark.skipif(
+ sys.version_info < (3, 13), reason="audioop-lts only on Python 3.13+"
+)
def test_audioop_lts_resolves_when_applicable():
v = ReticulumMeshChat.get_package_version("audioop-lts")
assert v != "unknown"

diff --git a/tests/backend/test_performance_bottlenecks.py b/tests/backend/test_performance_bottlenecks.py
index c1f41206..bee75b8f 100644
--- a/tests/backend/test_performance_bottlenecks.py
+++ b/tests/backend/test_performance_bottlenecks.py
@@ -196,7 +196,9 @@ class TestPerformanceBottlenecks(unittest.TestCase):
b"packet",
)
- threads = [threading.Thread(target=insert_announces) for _ in range(num_threads)]
+ threads = [
+ threading.Thread(target=insert_announces) for _ in range(num_threads)
+ ]
print(
f"\nRunning {num_threads} threads inserting {announces_per_thread} announces each...",

diff --git a/tests/backend/test_performance_hotpaths.py b/tests/backend/test_performance_hotpaths.py
index 073e7942..baf71708 100644
--- a/tests/backend/test_performance_hotpaths.py
+++ b/tests/backend/test_performance_hotpaths.py
@@ -512,7 +512,9 @@ class TestPerformanceHotPaths(unittest.TestCase):
with lock:
all_durations.extend(thread_durations)
- threads = [threading.Thread(target=writer, args=(t,)) for t in range(num_threads)]
+ threads = [
+ threading.Thread(target=writer, args=(t,)) for t in range(num_threads)
+ ]
t0 = time.perf_counter()
for t in threads:
t.start()
@@ -556,7 +558,9 @@ class TestPerformanceHotPaths(unittest.TestCase):
with lock:
all_durations.extend(thread_durations)
- threads = [threading.Thread(target=writer, args=(t,)) for t in range(num_threads)]
+ threads = [
+ threading.Thread(target=writer, args=(t,)) for t in range(num_threads)
+ ]
t0 = time.perf_counter()
for t in threads:
t.start()
@@ -619,8 +623,12 @@ class TestPerformanceHotPaths(unittest.TestCase):
with lock:
read_durations.extend(local_durs)
- writers = [threading.Thread(target=writer, args=(t,)) for t in range(num_writers)]
- readers = [threading.Thread(target=reader, args=(t,)) for t in range(num_readers)]
+ writers = [
+ threading.Thread(target=writer, args=(t,)) for t in range(num_writers)
+ ]
+ readers = [
+ threading.Thread(target=reader, args=(t,)) for t in range(num_readers)
+ ]
t0 = time.perf_counter()
for t in writers + readers:

diff --git a/tests/backend/test_propagation_nodes_robustness.py b/tests/backend/test_propagation_nodes_robustness.py
index e79834a1..db53b26d 100644
--- a/tests/backend/test_propagation_nodes_robustness.py
+++ b/tests/backend/test_propagation_nodes_robustness.py
@@ -67,7 +67,10 @@ async def test_propagation_nodes_endpoint_robustness(mock_rns_minimal, temp_dir)
assert "is_local_node" in node
if node.get("is_local_node") and isinstance(node.get("local_node_stats"), dict):
if isinstance(node["local_node_stats"].get("is_running"), bool):
- assert node.get("is_propagation_enabled") == node["local_node_stats"]["is_running"]
+ assert (
+ node.get("is_propagation_enabled")
+ == node["local_node_stats"]["is_running"]
+ )
# Test with invalid limit (should not crash)
request.query = {"limit": "invalid"}
@@ -79,7 +82,10 @@ async def test_propagation_nodes_endpoint_robustness(mock_rns_minimal, temp_dir)
assert "is_local_node" in node
if node.get("is_local_node") and isinstance(node.get("local_node_stats"), dict):
if isinstance(node["local_node_stats"].get("is_running"), bool):
- assert node.get("is_propagation_enabled") == node["local_node_stats"]["is_running"]
+ assert (
+ node.get("is_propagation_enabled")
+ == node["local_node_stats"]["is_running"]
+ )
# Test with missing limit (should not crash)
request.query = {}
@@ -91,4 +97,7 @@ async def test_propagation_nodes_endpoint_robustness(mock_rns_minimal, temp_dir)
assert "is_local_node" in node
if node.get("is_local_node") and isinstance(node.get("local_node_stats"), dict):
if isinstance(node["local_node_stats"].get("is_running"), bool):
- assert node.get("is_propagation_enabled") == node["local_node_stats"]["is_running"]
+ assert (
+ node.get("is_propagation_enabled")
+ == node["local_node_stats"]["is_running"]
+ )

diff --git a/tests/backend/test_rnode_download_firmware.py b/tests/backend/test_rnode_download_firmware.py
index 0a845ce8..ccf3a00d 100644
--- a/tests/backend/test_rnode_download_firmware.py
+++ b/tests/backend/test_rnode_download_firmware.py
@@ -98,7 +98,9 @@ async def test_download_firmware_returns_zip_for_allowed_url(web_app):
async with TestClient(TestServer(aio_app)) as client:
r = await client.get(
"/api/v1/tools/rnode/download_firmware",
- params={"url": "https://github.com/owner/repo/releases/download/v1/firmware.zip"},
+ params={
+ "url": "https://github.com/owner/repo/releases/download/v1/firmware.zip"
+ },
)
assert r.status == 200
assert r.headers.get("Content-Type", "").startswith("application/zip")
@@ -142,7 +144,9 @@ async def test_download_firmware_returns_500_on_exception(web_app):
async with TestClient(TestServer(aio_app)) as client:
r = await client.get(
"/api/v1/tools/rnode/download_firmware",
- params={"url": "https://github.com/owner/repo/releases/download/v1/firmware.zip"},
+ params={
+ "url": "https://github.com/owner/repo/releases/download/v1/firmware.zip"
+ },
)
assert r.status == 500
body = await r.json()

diff --git a/tests/backend/test_rnpath_logic.py b/tests/backend/test_rnpath_logic.py
index 9ba15164..b2ae8c41 100644
--- a/tests/backend/test_rnpath_logic.py
+++ b/tests/backend/test_rnpath_logic.py
@@ -70,7 +70,9 @@ async def test_rnpath_table_endpoint(mock_rns_minimal, temp_dir):
request.query = {}
handler = next(
- r.handler for r in app_instance.get_routes() if r.path == "/api/v1/rnpath/table"
+ r.handler
+ for r in app_instance.get_routes()
+ if r.path == "/api/v1/rnpath/table"
)
response = await handler(request)
data = json.loads(response.body)
@@ -96,7 +98,9 @@ async def test_rnpath_request_endpoint(mock_rns_minimal, temp_dir):
request.json = AsyncMock(return_value={"destination_hash": target_hash})
handler = next(
- r.handler for r in app_instance.get_routes() if r.path == "/api/v1/rnpath/request"
+ r.handler
+ for r in app_instance.get_routes()
+ if r.path == "/api/v1/rnpath/request"
)
response = await handler(request)
@@ -118,7 +122,9 @@ async def test_rnpath_drop_endpoint(mock_rns_minimal, temp_dir):
request.json = AsyncMock(return_value={"destination_hash": target_hash})
handler = next(
- r.handler for r in app_instance.get_routes() if r.path == "/api/v1/rnpath/drop"
+ r.handler
+ for r in app_instance.get_routes()
+ if r.path == "/api/v1/rnpath/drop"
)
response = await handler(request)

diff --git a/tests/backend/test_rns_lifecycle.py b/tests/backend/test_rns_lifecycle.py
index 060969c0..2e4d6830 100644
--- a/tests/backend/test_rns_lifecycle.py
+++ b/tests/backend/test_rns_lifecycle.py
@@ -528,7 +528,10 @@ async def test_transport_enable_endpoint_reloads_rns(mock_rns, temp_dir):
handler = None
for route in app.get_routes():
- if route.path == "/api/v1/reticulum/enable-transport" and route.method == "POST":
+ if (
+ route.path == "/api/v1/reticulum/enable-transport"
+ and route.method == "POST"
+ ):
handler = route.handler
break
@@ -538,7 +541,10 @@ async def test_transport_enable_endpoint_reloads_rns(mock_rns, temp_dir):
payload = json.loads(response.body)
assert response.status == 200
- assert payload["message"] == "Transport mode enabled and RNS restarted successfully."
+ assert (
+ payload["message"]
+ == "Transport mode enabled and RNS restarted successfully."
+ )
app.reload_reticulum.assert_awaited_once()
app.teardown_identity()
@@ -570,7 +576,10 @@ async def test_transport_disable_endpoint_reloads_rns(mock_rns, temp_dir):
handler = None
for route in app.get_routes():
- if route.path == "/api/v1/reticulum/disable-transport" and route.method == "POST":
+ if (
+ route.path == "/api/v1/reticulum/disable-transport"
+ and route.method == "POST"
+ ):
handler = route.handler
break
@@ -580,7 +589,10 @@ async def test_transport_disable_endpoint_reloads_rns(mock_rns, temp_dir):
payload = json.loads(response.body)
assert response.status == 200
- assert payload["message"] == "Transport mode disabled and RNS restarted successfully."
+ assert (
+ payload["message"]
+ == "Transport mode disabled and RNS restarted successfully."
+ )
app.reload_reticulum.assert_awaited_once()
app.teardown_identity()
@@ -612,7 +624,10 @@ async def test_transport_enable_endpoint_reload_failure(mock_rns, temp_dir):
handler = None
for route in app.get_routes():
- if route.path == "/api/v1/reticulum/enable-transport" and route.method == "POST":
+ if (
+ route.path == "/api/v1/reticulum/enable-transport"
+ and route.method == "POST"
+ ):
handler = route.handler
break
@@ -622,7 +637,10 @@ async def test_transport_enable_endpoint_reload_failure(mock_rns, temp_dir):
payload = json.loads(response.body)
assert response.status == 500
- assert payload["message"] == "Transport mode was enabled in config, but RNS reload failed."
+ assert (
+ payload["message"]
+ == "Transport mode was enabled in config, but RNS reload failed."
+ )
app.reload_reticulum.assert_awaited_once()
app.teardown_identity()
@@ -654,7 +672,10 @@ async def test_transport_disable_endpoint_reload_failure(mock_rns, temp_dir):
handler = None
for route in app.get_routes():
- if route.path == "/api/v1/reticulum/disable-transport" and route.method == "POST":
+ if (
+ route.path == "/api/v1/reticulum/disable-transport"
+ and route.method == "POST"
+ ):
handler = route.handler
break
@@ -664,7 +685,10 @@ async def test_transport_disable_endpoint_reload_failure(mock_rns, temp_dir):
payload = json.loads(response.body)
assert response.status == 500
- assert payload["message"] == "Transport mode was disabled in config, but RNS reload failed."
+ assert (
+ payload["message"]
+ == "Transport mode was disabled in config, but RNS reload failed."
+ )
app.reload_reticulum.assert_awaited_once()
app.teardown_identity()

diff --git a/tests/backend/test_security_fuzzing.py b/tests/backend/test_security_fuzzing.py
index f7eba93e..aac2fb2f 100644
--- a/tests/backend/test_security_fuzzing.py
+++ b/tests/backend/test_security_fuzzing.py
@@ -647,7 +647,9 @@ def test_lxm_uri_comprehensive_fuzzing(mock_app, uri):
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
try:
- uri_str = uri.decode("utf-8", errors="ignore") if isinstance(uri, bytes) else uri
+ uri_str = (
+ uri.decode("utf-8", errors="ignore") if isinstance(uri, bytes) else uri
+ )
loop.run_until_complete(
mock_app.on_websocket_data_received(
mock_client,
@@ -1122,17 +1124,20 @@ def test_map_tile_coordinates_fuzzing(mock_app, z, x, y):
try:
z_int = (
int(z)
- if isinstance(z, (int, float)) and (not isinstance(z, float) or math.isfinite(z))
+ if isinstance(z, (int, float))
+ and (not isinstance(z, float) or math.isfinite(z))
else 0
)
x_int = (
int(x)
- if isinstance(x, (int, float)) and (not isinstance(x, float) or math.isfinite(x))
+ if isinstance(x, (int, float))
+ and (not isinstance(x, float) or math.isfinite(x))
else 0
)
y_int = (
int(y)
- if isinstance(y, (int, float)) and (not isinstance(y, float) or math.isfinite(y))
+ if isinstance(y, (int, float))
+ and (not isinstance(y, float) or math.isfinite(y))
else 0
)
mock_app.map_manager.get_tile(z_int, x_int, y_int)
@@ -1399,7 +1404,9 @@ def test_nomadnet_page_archive_add_fuzzing(
import asyncio
content_str = (
- content.decode("utf-8", errors="replace") if isinstance(content, bytes) else content
+ content.decode("utf-8", errors="replace")
+ if isinstance(content, bytes)
+ else content
)
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
@@ -1936,7 +1943,10 @@ def test_lxmf_audio_mode_fuzzing(mock_app, audio_mode, audio_bytes):
)
def test_lxst_profile_switching_fuzzing(mock_app, profile_id):
"""Fuzz LXST audio profile switching."""
- if hasattr(mock_app.telephone_manager, "telephone") and mock_app.telephone_manager.telephone:
+ if (
+ hasattr(mock_app.telephone_manager, "telephone")
+ and mock_app.telephone_manager.telephone
+ ):
mock_app.telephone_manager.telephone.switch_profile(profile_id)
@@ -2176,11 +2186,15 @@ def test_lxmf_display_name_parsing_regression():
# None case (fallback to default)
mock_parser.return_value = None
- assert parse_lxmf_display_name(valid_b64, default_value="Fallback") == "Fallback"
+ assert (
+ parse_lxmf_display_name(valid_b64, default_value="Fallback") == "Fallback"
+ )
# Exception case
mock_parser.side_effect = Exception("Parsing error")
- assert parse_lxmf_display_name(valid_b64, default_value="Fallback") == "Fallback"
+ assert (
+ parse_lxmf_display_name(valid_b64, default_value="Fallback") == "Fallback"
+ )
# None input
assert parse_lxmf_display_name(None, default_value="Fallback") == "Fallback"

diff --git a/tests/backend/test_startup.py b/tests/backend/test_startup.py
index b02de103..b44b46a0 100644
--- a/tests/backend/test_startup.py
+++ b/tests/backend/test_startup.py
@@ -114,14 +114,18 @@ def test_reticulum_meshchat_init(mock_rns, temp_dir):
# Setup config mock values
mock_config_instance.auth_enabled.get.return_value = False
mock_config_instance.lxmf_propagation_node_stamp_cost.get.return_value = 0
- mock_config_instance.lxmf_delivery_transfer_limit_in_bytes.get.return_value = 1000000
+ mock_config_instance.lxmf_delivery_transfer_limit_in_bytes.get.return_value = (
+ 1000000
+ )
mock_config_instance.lxmf_inbound_stamp_cost.get.return_value = 0
mock_config_instance.display_name.get.return_value = "Test User"
- mock_config_instance.lxmf_preferred_propagation_node_destination_hash.get.return_value = (
- None
+ mock_config_instance.lxmf_preferred_propagation_node_destination_hash.get.return_value = None
+ mock_config_instance.lxmf_local_propagation_node_enabled.get.return_value = (
+ False
+ )
+ mock_config_instance.libretranslate_url.get.return_value = (
+ "http://localhost:5000"
)
- mock_config_instance.lxmf_local_propagation_node_enabled.get.return_value = False
- mock_config_instance.libretranslate_url.get.return_value = "http://localhost:5000"
mock_config_instance.translator_enabled.get.return_value = False
app = ReticulumMeshChat(

diff --git a/tests/backend/test_sticker_pack_utils.py b/tests/backend/test_sticker_pack_utils.py
index 7d68aadb..8b1f1cc2 100644
--- a/tests/backend/test_sticker_pack_utils.py
+++ b/tests/backend/test_sticker_pack_utils.py
@@ -19,7 +19,10 @@ def test_sanitize_pack_title_default():
def test_sanitize_pack_short_name():
assert sticker_pack_utils.sanitize_pack_short_name(None) is None
assert sticker_pack_utils.sanitize_pack_short_name("Cats!@#") == "cats"
- assert sticker_pack_utils.sanitize_pack_short_name(" Hello_World-1 ") == "hello_world-1"
+ assert (
+ sticker_pack_utils.sanitize_pack_short_name(" Hello_World-1 ")
+ == "hello_world-1"
+ )
assert sticker_pack_utils.sanitize_pack_short_name("***") is None
assert len(sticker_pack_utils.sanitize_pack_short_name("a" * 200)) == 32

diff --git a/tests/backend/test_sticker_utils.py b/tests/backend/test_sticker_utils.py
index edfdfb42..93e20049 100644
--- a/tests/backend/test_sticker_utils.py
+++ b/tests/backend/test_sticker_utils.py
@@ -59,13 +59,24 @@ def test_validate_sticker_payload_magic_type_mismatch():
def test_detect_image_format_from_magic():
assert sticker_utils.detect_image_format_from_magic(b"\x89PNG\r\n\x1a\n") == "png"
- assert sticker_utils.detect_image_format_from_magic(b"\xff\xd8\xff\xe0\x00\x10") == "jpeg"
- assert sticker_utils.detect_image_format_from_magic(b"GIF89a" + b"\x00" * 4) == "gif"
+ assert (
+ sticker_utils.detect_image_format_from_magic(b"\xff\xd8\xff\xe0\x00\x10")
+ == "jpeg"
+ )
+ assert (
+ sticker_utils.detect_image_format_from_magic(b"GIF89a" + b"\x00" * 4) == "gif"
+ )
assert sticker_utils.detect_image_format_from_magic(b"BM" + b"\x00" * 20) == "bmp"
webp = b"RIFF\x00\x00\x00\x00WEBP" + b"\x00" * 8
assert sticker_utils.detect_image_format_from_magic(webp) == "webp"
- assert sticker_utils.detect_image_format_from_magic(b"\x1a\x45\xdf\xa3" + b"\x00" * 8) == "webm"
- assert sticker_utils.detect_image_format_from_magic(b"\x1f\x8b\x08\x00" + b"\x00" * 8) == "tgs"
+ assert (
+ sticker_utils.detect_image_format_from_magic(b"\x1a\x45\xdf\xa3" + b"\x00" * 8)
+ == "webm"
+ )
+ assert (
+ sticker_utils.detect_image_format_from_magic(b"\x1f\x8b\x08\x00" + b"\x00" * 8)
+ == "tgs"
+ )
assert sticker_utils.detect_image_format_from_magic(b"") is None
assert sticker_utils.detect_image_format_from_magic(b"short") is None
@@ -188,7 +199,9 @@ def test_validate_export_document_fuzz_never_raises_unexpected(doc):
pass
-def _build_tgs(width: int = 512, height: int = 512, fps: float = 30.0, frames: int = 60) -> bytes:
+def _build_tgs(
+ width: int = 512, height: int = 512, fps: float = 30.0, frames: int = 60
+) -> bytes:
import gzip
import json
@@ -234,7 +247,9 @@ def test_parse_tgs_invalid_metadata():
import gzip
import json
- raw = gzip.compress(json.dumps({"w": 0, "h": 0, "fr": 0, "ip": 0, "op": 0}).encode())
+ raw = gzip.compress(
+ json.dumps({"w": 0, "h": 0, "fr": 0, "ip": 0, "op": 0}).encode()
+ )
with pytest.raises(ValueError, match="invalid_tgs_metadata"):
sticker_utils.parse_tgs(raw)
@@ -290,7 +305,11 @@ def test_validate_strict_webm_too_large():
def test_detect_image_dimensions_png():
- raw = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR" + struct_pack(512, 512) + b"\x08\x06\x00\x00\x00"
+ raw = (
+ b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR"
+ + struct_pack(512, 512)
+ + b"\x08\x06\x00\x00\x00"
+ )
assert sticker_utils.detect_image_dimensions("png", raw) == (512, 512)
@@ -329,7 +348,11 @@ def test_extract_metadata_tgs():
def test_extract_metadata_static_png():
- raw = b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR" + struct_pack(512, 256) + b"\x08\x06\x00\x00\x00"
+ raw = (
+ b"\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR"
+ + struct_pack(512, 256)
+ + b"\x08\x06\x00\x00\x00"
+ )
meta = sticker_utils.extract_metadata("png", raw)
assert meta["width"] == 512
assert meta["height"] == 256

diff --git a/tests/backend/test_telemetry_integration.py b/tests/backend/test_telemetry_integration.py
index 0ef2fb84..85ea40ec 100644
--- a/tests/backend/test_telemetry_integration.py
+++ b/tests/backend/test_telemetry_integration.py
@@ -36,8 +36,8 @@ def mock_app():
# Attach the actual method we want to test if possible,
# but since it's an instance method, we might need to bind it.
- app.process_incoming_telemetry = ReticulumMeshChat.process_incoming_telemetry.__get__(
- app, ReticulumMeshChat
+ app.process_incoming_telemetry = (
+ ReticulumMeshChat.process_incoming_telemetry.__get__(app, ReticulumMeshChat)
)
return app

diff --git a/tests/backend/test_telephone_api_json_contracts.py b/tests/backend/test_telephone_api_json_contracts.py
index baebb4db..f95f3eda 100644
--- a/tests/backend/test_telephone_api_json_contracts.py
+++ b/tests/backend/test_telephone_api_json_contracts.py
@@ -73,14 +73,18 @@ class _Query:
@pytest.mark.asyncio
-async def test_api_v1_telephone_voicemail_status_json_contract(mock_rns_minimal, temp_dir):
+async def test_api_v1_telephone_voicemail_status_json_contract(
+ mock_rns_minimal, temp_dir
+):
with patch("meshchatx.meshchat.generate_ssl_certificate"):
app_instance = ReticulumMeshChat(
identity=mock_rns_minimal,
storage_dir=temp_dir,
reticulum_config_dir=temp_dir,
)
- handler = _find_handler(app_instance, "/api/v1/telephone/voicemail/status", "GET")
+ handler = _find_handler(
+ app_instance, "/api/v1/telephone/voicemail/status", "GET"
+ )
assert handler is not None
request = MagicMock()
response = await handler(request)
@@ -106,7 +110,9 @@ async def test_api_v1_telephone_voicemails_json_contract(mock_rns_minimal, temp_
@pytest.mark.asyncio
-async def test_api_v1_telephone_ringtones_list_json_contract(mock_rns_minimal, temp_dir):
+async def test_api_v1_telephone_ringtones_list_json_contract(
+ mock_rns_minimal, temp_dir
+):
with patch("meshchatx.meshchat.generate_ssl_certificate"):
app_instance = ReticulumMeshChat(
identity=mock_rns_minimal,
@@ -122,14 +128,18 @@ async def test_api_v1_telephone_ringtones_list_json_contract(mock_rns_minimal, t
@pytest.mark.asyncio
-async def test_api_v1_telephone_ringtones_status_json_contract(mock_rns_minimal, temp_dir):
+async def test_api_v1_telephone_ringtones_status_json_contract(
+ mock_rns_minimal, temp_dir
+):
with patch("meshchatx.meshchat.generate_ssl_certificate"):
app_instance = ReticulumMeshChat(
identity=mock_rns_minimal,
storage_dir=temp_dir,
reticulum_config_dir=temp_dir,
)
- handler = _find_handler(app_instance, "/api/v1/telephone/ringtones/status", "GET")
+ handler = _find_handler(
+ app_instance, "/api/v1/telephone/ringtones/status", "GET"
+ )
assert handler is not None
request = MagicMock()
request.query = _Query({})
@@ -156,7 +166,9 @@ async def test_api_v1_telephone_contacts_list_json_contract(mock_rns_minimal, te
@pytest.mark.asyncio
-async def test_api_v1_telephone_contacts_check_json_contract(mock_rns_minimal, temp_dir):
+async def test_api_v1_telephone_contacts_check_json_contract(
+ mock_rns_minimal, temp_dir
+):
with patch("meshchatx.meshchat.generate_ssl_certificate"):
app_instance = ReticulumMeshChat(
identity=mock_rns_minimal,

diff --git a/tests/backend/test_telephone_initiation.py b/tests/backend/test_telephone_initiation.py
index f2d24a54..53688e96 100644
--- a/tests/backend/test_telephone_initiation.py
+++ b/tests/backend/test_telephone_initiation.py
@@ -21,7 +21,9 @@ def telephone_manager():
tm._path_retry_interval_s = 0.01
tm._status_poll_interval_s = 0.01
tm._status_events = []
- tm.on_initiation_status_callback = lambda status, _target: tm._status_events.append(status)
+ tm.on_initiation_status_callback = lambda status, _target: tm._status_events.append(
+ status
+ )
return tm
@@ -48,7 +50,9 @@ async def test_initiate_retries_path_requests_during_lookup(telephone_manager):
"meshchatx.src.backend.telephone_manager.RNS.Transport.has_path",
side_effect=has_path,
),
- patch("meshchatx.src.backend.telephone_manager.RNS.Transport.request_path") as request_path,
+ patch(
+ "meshchatx.src.backend.telephone_manager.RNS.Transport.request_path"
+ ) as request_path,
):
await telephone_manager.initiate(destination_hash, timeout_seconds=1)
@@ -79,7 +83,9 @@ async def test_initiate_cancels_quickly_while_finding_path_identity(telephone_ma
side_effect=request_path_and_cancel,
),
):
- task = asyncio.create_task(telephone_manager.initiate(destination_hash, timeout_seconds=5))
+ task = asyncio.create_task(
+ telephone_manager.initiate(destination_hash, timeout_seconds=5)
+ )
result = await asyncio.wait_for(task, timeout=0.3)
assert result is None
@@ -105,7 +111,9 @@ async def test_initiate_cancels_quickly_while_dialling(telephone_manager):
return_value=True,
),
):
- task = asyncio.create_task(telephone_manager.initiate(destination_hash, timeout_seconds=5))
+ task = asyncio.create_task(
+ telephone_manager.initiate(destination_hash, timeout_seconds=5)
+ )
for _ in range(200):
if telephone_manager.initiation_status in (
"Establishing link...",
@@ -170,7 +178,9 @@ async def test_cancel_after_path_found_before_dialling_stabilizes(telephone_mana
return_value=True,
),
):
- task = asyncio.create_task(telephone_manager.initiate(destination_hash, timeout_seconds=2))
+ task = asyncio.create_task(
+ telephone_manager.initiate(destination_hash, timeout_seconds=2)
+ )
for _ in range(200):
if telephone_manager.initiation_status == "Establishing link...":
break
@@ -275,7 +285,9 @@ async def test_call_thread_exception_surfaces_without_hanging(telephone_manager)
"meshchatx.src.backend.telephone_manager.RNS.Transport.has_path",
return_value=True,
),
- patch("meshchatx.src.backend.telephone_manager.asyncio.sleep", side_effect=no_wait),
+ patch(
+ "meshchatx.src.backend.telephone_manager.asyncio.sleep", side_effect=no_wait
+ ),
):
result = await asyncio.wait_for(
telephone_manager.initiate(destination_hash, timeout_seconds=1),
@@ -307,7 +319,9 @@ async def test_inconsistent_call_status_finishes_within_timeout(telephone_manage
"meshchatx.src.backend.telephone_manager.RNS.Transport.has_path",
return_value=True,
),
- patch("meshchatx.src.backend.telephone_manager.asyncio.sleep", side_effect=no_wait),
+ patch(
+ "meshchatx.src.backend.telephone_manager.asyncio.sleep", side_effect=no_wait
+ ),
):
result = await asyncio.wait_for(
telephone_manager.initiate(destination_hash, timeout_seconds=0.2),
@@ -360,8 +374,10 @@ async def test_lxst_busy_and_rejected_end_without_stuck_status(telephone_manager
for terminal_state in (0, 1):
telephone_manager._status_events.clear()
telephone_manager.telephone.call_status = 3
- telephone_manager.telephone.call.side_effect = lambda _identity, state=terminal_state: (
- setattr(telephone_manager.telephone, "call_status", state)
+ telephone_manager.telephone.call.side_effect = (
+ lambda _identity, state=terminal_state: setattr(
+ telephone_manager.telephone, "call_status", state
+ )
)
with (

diff --git a/tests/backend/test_telephone_manager_boost.py b/tests/backend/test_telephone_manager_boost.py
index b873a6aa..77732eb7 100644
--- a/tests/backend/test_telephone_manager_boost.py
+++ b/tests/backend/test_telephone_manager_boost.py
@@ -42,12 +42,16 @@ def test_init_telephone(mock_tel_class, tel_manager):
@patch("meshchatx.src.backend.telephone_manager.Telephone")
-def test_init_telephone_applies_config_audio_profile(mock_tel_class, mock_identity, tmp_path):
+def test_init_telephone_applies_config_audio_profile(
+ mock_tel_class, mock_identity, tmp_path
+):
storage_dir = tmp_path / "tel"
storage_dir.mkdir()
cfg = MagicMock()
cfg.telephone_audio_profile_id.get.return_value = 96
- tm = TelephoneManager(mock_identity, config_manager=cfg, storage_dir=str(storage_dir))
+ tm = TelephoneManager(
+ mock_identity, config_manager=cfg, storage_dir=str(storage_dir)
+ )
tm.init_telephone()
mock_tel_class.return_value.switch_profile.assert_called_with(96)

diff --git a/tests/backend/test_user_guidance_autointerface.py b/tests/backend/test_user_guidance_autointerface.py
index 29e50b0f..9a65036e 100644
--- a/tests/backend/test_user_guidance_autointerface.py
+++ b/tests/backend/test_user_guidance_autointerface.py
@@ -20,7 +20,9 @@ def _make_app(config_interfaces):
transport_enabled=lambda: True,
)
app._get_interfaces_section = ReticulumMeshChat._get_interfaces_section.__get__(app)
- app._detect_failed_autointerfaces = ReticulumMeshChat._detect_failed_autointerfaces.__get__(app)
+ app._detect_failed_autointerfaces = (
+ ReticulumMeshChat._detect_failed_autointerfaces.__get__(app)
+ )
return app
@@ -102,7 +104,9 @@ def test_guidance_message_emitted_for_failed_autointerface():
)
app.config = MagicMock()
app.config.auto_announce_enabled.get.return_value = True
- app.build_user_guidance_messages = ReticulumMeshChat.build_user_guidance_messages.__get__(app)
+ app.build_user_guidance_messages = (
+ ReticulumMeshChat.build_user_guidance_messages.__get__(app)
+ )
with patch("meshchatx.meshchat.RNS.Transport") as transport:
transport.interfaces = []
@@ -125,7 +129,9 @@ def test_guidance_message_absent_when_autointerface_running():
)
app.config = MagicMock()
app.config.auto_announce_enabled.get.return_value = True
- app.build_user_guidance_messages = ReticulumMeshChat.build_user_guidance_messages.__get__(app)
+ app.build_user_guidance_messages = (
+ ReticulumMeshChat.build_user_guidance_messages.__get__(app)
+ )
with patch("meshchatx.meshchat.RNS.Transport") as transport:
transport.interfaces = [_FakeAutoInterface()]


──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────